I don't know what the compilar is doing with ++*p;
Can anyone explain me pictorically what is going on inside the memory in this code?
int main()
{
int arr[]={1,2,3,4};
int *p;
p=arr;
++*p;
printf("%d",*p);
}
The answer should be 2
The reason is ++*p is is actually incrementing the first member in the array by 1.
You are incrementing the first element in that array by creating another int pointer p that points to the element. The line
++*p
increments the value of the object pointed to by p - in this case it is the first element in the array.
Making up the actual memory addresses and using "ma" for memory address
at memory address starting at 1000 we have 4 continuous 4-byte (sizeof(int) = 4) slots.
each slot contains the integer value given in the array initializer:
arr
ma1000 ... ma1015
_____________________
| 1| 2| 3| 4|
_____________________
arr gives the starting address of the 4 int slots and how many there are.
p holds the address of an integer and refers to one 8-byte slot in memory (assuming we are on a 64-bit system where pointers are 8 bytes - 64 address bits/8bits-per-byte) at location 2000.
After the statement p = arr, p holds the address 1000
p *p or arr[0]
ma2000 .. ma2007 ma1000 .. ma1003
__________ ________
| 1000| | 1 |
__________ ________
*p gives the value at the memory address pointed to by p. p holds memory address 1000 and memory address 1000 contains 1, thus *p results in 1.
++*p says to increment the value of the int "pointed to" by p. p holds memory address 1000 which holds the value 1. The value at address 1000 then goes from 1 to 2
arr
ma1000 ... ma1015
_____________________
| 2| 2| 3| 4|
_____________________
printf then prints the int value at the address "pointed to" by p, which is 2.
p *p or arr[0]
ma2000 .. ma2007 ma1000 .. ma1003
___________ ___________
| 1000| | 2|
___________ ___________
Let's take this line :
++*p
This will first dereference the p pointer, so access arr[0], then increment it.
if you print arr[0] now, it will be 2.
Then you print *p that is the same as printing arr[0], it equals 2.
Try replacing the first element by 41, your code will print 42.
When you have a pointer int *p, then p means "the memory address p points to and *p means "the contents of the memory address where p points to". ++ means pre-increment, which means increase the value by 1. Since the associativity of unary operators such as * and ++(prefix operators) is right-to-left, and * is closer to p than ++ when traversed right-to-left, * operates before ++. Therefore ++*p means "increment the value pointed to by p", not "increment p then get the value". It is clearer to write ++(*p), but it means the same thing.
The thing to understand is the difference between "increment the pointer", which means point to another value (e.g. ++p) and "increment the value that the pointer points to" (e.g. ++*p).
You can work this out, but that is all the information you need to understand it.
This is a very basic concept in understanding of pointers.
p = arr ;
The above code will make the pointer " p " to point towards what the " arr " is pointing to. " arr " itself is pointing to the 1st element.
*arr = *(arr + 0) = arr[0] = 1
*(arr + 1) = arr[1] = 2
*(arr + 2) = arr[2] = 3
and so on...
So now when you do ++(*arr) that means ++(1) = 2
As p = arr, you can do the remaining replacement and math.
Related
int a=10;
int *p=&a;
now looking at &*p we first look at *p which is 10 and then at &10
which is the address of 10 or the address of a
In the case of *&p we first look at the address of p and then at the value in this address which is 10
But I understand that both *&p vs &*p are the same, why?
Lets draw your variables:
+---+ +---+
| p | --> | a |
+---+ +---+
That is, p is pointing to a.
Now if you do &*p then you first dereference p to get a, then you get the address of a, which leaves you with a pointer to a.
If we take *&p then you get the address of p to get a pointer to p, then you dereference that pointer to get p. Which is a pointer to a.
So while the expressions do different things, the end result is the same: A pointer to a.
And a descent compiler would probably just do nothing at all, since the dereference operator * and address-of operator & together will always cancel each other out, no matter in which order they are.
Considering below example
int a=10;
int *p=&a;
this
*&p
means here both * and & gets nullified and it result in p which is nothing but &a.
And this
&*p
means first dereference p which gives a and then reference & i.e address of a which is nothing but p, same as the first case.
By the clockwise / spiral rule:
For *&p:
+-----+
| +-+ |
| ^ | |
* & p ; |
^ ^ | |
| +---+ |
+-------+
We first take the address of p, which is at this point the address of the address of a.
Then we dereference that, which gives the address of a.
For &*p:
+-----+
| +-+ |
| ^ | |
& * p ; |
^ ^ | |
| +---+ |
+-------+
We first dereference p, which gives us a.
We then take the address of that, which gives us the address of a, just like before.
In this context, & takes the address (i.e., informally "adds *" to the type of the expression). Meanwhile * dereferences a pointer (i.e., "removes a *" from the type of the expression). Therefore:
int *p = …;
p; // int *
*p; // int
&*p; // int *
&p; // int **
*&p; // int *
So, yes, in this context the result is the same: a pointer to int, because the & and the * cancel out. However, this is also why the combinations are pointless: the result is the same as p by itself.
*&p == *(&p). &p is an pointer to the pointer or int. *(&p) is a value to which pointer of pointer points, which is value of p. To continue, **&p will print '10'.
&*p == &(*p) where *p is the value at which the pointer points (value of a). Now & is an address of a, which is p again. And to go further, *&*p will print value of a (10).
1) #include <stdio.h>
int main()
{
int a[5] = {1,2,3,4,5};
int *ptr = (int*)(&a+1);
printf("%d %d", *(a+1), *(ptr-1));
return 0;
}
the output is 2 5. &a means the address of a[0] so &a+1 should be the address of a[1]. So ptr should hold the address of a[1]. *(a+1) will be 2 but *(ptr-1) should also be 2. I can't understand how is it printing 5.
This expression is the important thing: &a+1. That is actually (&a)+1 which is equal to (&a)[1] which will be a pointer to one element past the end of the array.
If we look at it more "graphically" it looks like this, with relevant pointers added:
+------+------+------+------+------+
| a[0] | a[1] | a[2] | a[3] | a[4] |
+------+------+------+------+------+
^ ^ ^
| | |
| &a[1] (equal to *(a + 1)) |
| |
&a[0] (equal to a) |
| |
&a &a+1
First of all, the type of &a is int (*)[5], so your cast to int * will break strict aliasing (which leads to undefined behavior).
Second of all, since ptr is pointing, effectively, to what would be a[5] then ptr - 1 will point to a[4].
&a is not the address of a[0] but the address of a. The values may be the same but the types are different. That is important when it comes to pointer arithmetic.
In the expression &a + 1, you first have &a which has type int (*)[5], i.e. a pointer to an array of size 5. When you add 1 to that it actually adds sizeof(a) bytes to the pointer value. So &a + 1 actually points to one byte past the end of the array. You then cast this expression from int (*)[5] to int * and assign it to ptr.
When you then evaluate *(ptr - 1), the - operator subtracts 1 * sizeof(int) from the byte value of ptr so it now points to the last element of the array, i.e. 5, and that is what is printed.
&a gives the address of the array as an array pointer, int (*)[5]. It is a pointer type that points at the array as whole, so if you do pointer arithmetic with it, +1 will mean +sizeof(int[5]) which is not what you intended.
Correct code:
int *ptr = a+1;
Notably, the cast (int*) was hiding this bug. Don't use casts to silence compiler errors you don't understand!
Firstly, you said: &a means the address of a[0] so &a+1 should be the address of a[1] ? No you are wrong. &a means address of a not a[0]. And &a+1 means it increments by whole array size not just one elements size and a+1 means address of a[1].
Here
int a[5] = {1,2,3,4,5};
lets assume base address of a is 0x100
--------------------------------------
| 1 | 2 | 3 | 4 | 5 |
--------------------------------------
0x100 0x104 0x108 0x112 0x116 ..
LSB
|
a
When you are doing
int *ptr = (int*)(&a+1);
Where ptr points ? first (&a+1) performed and it got increments by whole array size i.e
(&a+1) == (0x100 + 1*20) /* &a+1 here it increments by array size */
== 0x120
So now ptr points to
--------------------------------------
| 1 | 2 | 3 | 4 | 5 |
--------------------------------------
0x100 0x104 0x108 0x112 0x116 0x120
a |
ptr points here
Now when you print like
printf("%d %d", *(a+1), *(ptr-1));
Here
*(a+1) == *(0x100 + 1*4) /* multiplied by 4 bcz of elements is of int type*/
== *(0x104) /* value at 0x104 location */
== 2 (it prints 2)
And
*(ptr-1) == *(0x120 - 1*4)
== *(0x116) /* prints value at 0x116 memory location */
== 5
Note :- Here
int *ptr = (int*)(&a+1);
type of &a is of int(*)[5] i.e pointer to an array of 5 elements but you are casting as of int* type, as pointed by #someprogrammerdude it breaks the strict aliasing and lead to undefined behavior.
Correct one is
int *ptr = a+1;
I want to know whether &a[i] and &a[i-1]+sizeof(int) print the same value of address?
When i printed values it came different.How is it ? eg.say a[0] is at 1000 and a[1] at 1002 , then both a[1] and &a[i-1]+sizeof(int) where i=1 should return same right?
code snippet:
{
int a[3]={100,200,300};
print &a[1] and print &a[0]+sizeof(int)
}
a is of type array and &a is of type pointer. Their types are not the same.
This &a+1 is pointer arithmetic. Increasing the &a by 1 will take you to last position + 1 in the array. Example (assuming size is 5):
|0|1|2|3|4| |
a^ ^
&a+1^
The type of a is int[size] (for e.g.) that decays into address of first element in expression a + 1, adding one results points to second element in a; whereas type of &a is int(*)[size].
Stressing again their types are not the same. The type of pointer determines where you land next in memory, theoretically its something like:
address2 = BlockAddress + sizeof(TYPE)*IncrementVal
Of course not. On several machines, sizeof(int) is 4. &a[i-1]+sizeof(int) is &a[i-1]+4 which is &a[i+3] i.e. a+i+3
The addition on pointers (i.e. p+n where p is a pointer -or an array- and n is an integer) works in units of the type referenced by p. So if p points to a struct of 1024 bytes, p+1 has an address 1024 greater than p
I'm kinda confused:
int* p=1000;
printf("%d\n", (int)(p+sizeof(int))); // what is going on here?
does p point to 1000 or does p = the memory address 1000? If it is the former, could this be achieved achieved like this:
int dummyVariable = 1000;
int * p = &dummyVariable;
The declaration
int* p=1000;
makes p point to the address 1000.
While in the case of
int dummyVariable = 1000;
int * p = &dummyVariable;
you initialize dummyVariable to the value 1000 and make p point to dummyVariable.
Another way to look at it:
In the first case you have
Address 1000
|
v
+---+ +-----+
| p | --> | ??? |
+---+ +-----+
And in the second case you have
Address &dummyVariable
|
v
+---+ +----------------------------+
| p | --> | dummyVariable (value 1000) |
+---+ +----------------------------+
A third way of looking at it, is that the value of p is an integer (that just happens to be an address). In the first case p contains the value 1000, i.e. it's pointing to the address 1000.
In the second case the contents of p is &dummyVariable, i.e. it points to the location in memory where dummyVariable is stored.
As for the printout in the first example giving you the value 1016, that's because of how pointer arithmetic works: Whatever you add to a pointer is multiplied by the size of the base type. So if you have a pointer to int, then everything you add to that pointer will be multiplied by sizeof int.
In your case, the size of int is 4 bytes, so what you are doing is actually 1000 + 4 * 4 which is equal to 1016.
In your example, p is storing the memory address 1000, whatever that memory address is holding. In fact, p resides at another memory address, which, again stores the number 1000, which is a memory address, etc. Your second example is correct: The pointer p is assigned the memory address of dummyVariable, now if you modify dummyVariable or the *p (dereferencing the pointer), the changes will be applied to both (because they point to the same memory space).
int* p=1000;
p is a pointer pointing to memory location 1000.
printf("%d\n", (int)(p+sizeof(int)));
You are trying to access some memory here.( 1000 + sizeof(int))
Directly assigning some random address to a pointer as done here is not a good idea.
You should have got below mentioned warnings:
warning: initialization makes pointer from integer without a cast
warning: cast from pointer to integer of different size
The second part:
int dummyVariable = 1000;
int * p = &dummyVariable;
Here 1000 is a value and pointer p is pointing to a memory location holding 1000.
So both are diffrent.
I was writing this program -
#include<stdio.h>
void main()
{
int arr[20];
arr[0]=22;
arr[1]=23;
int (*p)[20]=&arr;
printf("address in p :%u:\n",p);
printf("address in *p:%u:\n",*p);
}
The Output of this code is same for p and *p ! So far as I know *p is holding the base address of arr which is nothing but arr[0]!!!
So *p should have give the output 22 ! But it's showing the same memory address like p is showing. Please tell me why this is happened? What is the reason behind it.
Codepad Site Link : http://codepad.org/LK7qXaqt
p is a pointer to an array of 20 integers. Address of first byte of array is said to be the address of the array. Dereferencing it will give the entire array itself. Therefore *p represents the array arr, so you can think of *p as an array name.
As array names are converted to pointers to its first element when passed to a function, *p is decayed to pointer to first element of arr. Therefore
printf("address in *p: %p:\n", (void*)*p);
will print the address of first element of array arr while
printf("address in p: %p:\n", (void*)p);
will print the address of the entire array (i.e first byte of the array). Since value of first byte and first element is same, that's why both are printing the same address.
For detailed explanation: What exactly is the array name in c?
Because p and *p points to same memory location only there types are different
+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+
arr [ ]
p [ ]
(*p)[ ]
If you print p+1 and *p + 1 you should see the difference
int (*p)[20] declare p as pointer to array of size 20 of type int so at the same time *p is the pointer to the first element of the array.
Address of first element and of whole array would be same.
Yes it is possible to apply the address operator to an array, although it seems redundant. The result p is a pointer to array. Such a thing is under normal circumstances rarely encountered. As #Mohit pointed out correctly, the object it points to is the whole array, which implies that sizeof(*p) should be the size of the array (not of its first element).
*p logically is the array then; as usual it decays to a pointer to its first element (which is an int) when passed as an argument, e.g. to printf. Since it's the first element its location in memory is the location of (the beginning of) the whole array.