Both expressions &arr+1
and arr+1
do not give the same result and this is verified with the following example:
int main(void)
{
int arr[] = {40, 41, 42, 43};
int* ptr = &arr+1;
int*ptr2 = arr + 1;
printf("%d, %d\n", *(ptr-1), *ptr2);
return 0;
}
The result on the screen is:
43,41
The million dollar question: Why *(ptr-1)
did it result in 43
?
Because it is clear that *ptr2
it returns a 41
, since it has the memory address of the second element of the array.
The problem is that although they both
arr
refer&arr
to the same address, they are nevertheless not the same type .arr
is of type "address of int" , since it is equivalent to putting&arr[0]
and inarr[0]
there is an integer, so itarr
is an address of an integer.Instead
&arr
it is of type "array address of 4 int" , because effectively what is in the address ofarr
is an array of 4 integers.The difference in type affects pointer arithmetic, which is how much is actually incremented when 1 is added to it.
If you have a pointer to
tipo
something, and you add 1 to the pointer, it will actually addsizeof(tipo)
, to point to the next element of that type. So:arr+1
, since as we have seen itarr
points to an integer, it will actually addsizeof(int)
, which is usually 4 bytes. Soptr2
in your code it will point to a position that is 4 bytes after the start of the array. So it will point to the next integer.&arr+1
, since as we have seen it&arr
points to an array of 4 integers, it will actually addsizeof(arr)
, which in this case is4*sizeof(int)
, and will therefore be 16 bytes (assuming that itsizeof(int)
is 4). So it would be pointing to a hypothetical array of four integers that would go afterarr
, although you don't have such a thing in the program. The pointerptr
is therefore wrongly assigned and in fact the types do not match because you declared itptr
as a pointer toint
, but you assign a pointer to an array of 4 ints. You will have a warning on that line.All of the above is demonstrated with this program:
The format string
%p
is often used to dump pointer values. Actually they just dump the address in question in hexadecimal. In the firstprintf()
one we dump the address ofarr
and that of&arr
, to verify that both are equal. In the second,printf()
we dump the values of the pointers to check that the first has been increased by 16 and the second by 4, with respect to the address of the array.The execution produces:
which matches what is expected (remember that 10 hex is 16)
Because because you declared
ptr
pointer to as typeint
, pointer arithmeticptr-1
will actually subtract fromsizeof(int)
, or 4 bytes. Recall that as explained before itptr
pointed 16 bytes beyond the beginning ofarr
, that is, to the first position "out" of that array. By subtracting 1 from the pointer (4 bytes to the address) it points to the last element ofarr
.