In the below two lines,
char a[5]={1,2,3,4,5};
char *ptr=(char *)(&a+1);
printf(\"%d\",*(ptr-1));
This prints 5 on screen.Whereas when use
Since you seem totally new to it let me explain it to you in simple terms instead of going for the rigorous explanation.
You see, for your program above, a
and &a
will have the same numerical value,and I believe that's where your whole confusion lies.You may wonder that if they are the same,the following should give the next address after a
in both cases,going by pointer arithmetic:
(&a+1) and (a+1)
But it's not so!!Base address of an array (a
here) and Address of an array are not same! a
and &a
might be same numerically ,but they are not the same type. a
is of type char*
while &a
is of type char (*)[5]
,ie , &a
is a pointer to (address of ) and array of size 5.But a
as you know is the address of the first element of the array.Numerically they are the same as you can see from the illustration using ^ below.
But when you increment these two pointers/addresses, ie as (a+1)
and (&a+1)
, the arithmetic is totally different.While in the first case it "jumps" to the address of the next element in the array, in the latter case it jumps by 5 elements as that's what the size of an array of 5 elements is!.Got it now?
1 2 3 4 5
^ // ^ stands at &a
1 2 3 4 5
^ // ^ stands at (&a+1)
1 2 3 4 5
^ //^ stands at a
1 2 3 4 5
^ // ^ stands at (a+1)
The following will give an error about unspecified bound for array as not explicitly specifying the size as below means the program won't know how many elements to "jump" to when something like (&a+1) is encountered.
char a[]={1,2,3,4,5};
char *ptr=(char *)(&a+1); //(&a+1) gives error as array size not specified.
Now to the part where you decrement the pointers/addresses as (ptr-1)
.In the first case, before you come to the decrement part, you should know what happens in the statement above it where it is cast to type char*
:
char *ptr=(char *)(&a+1);
What happens here is that you "strip off" the original type
of (&a+1)
which was type char (*)[5]
and now cast it to type char*
which is the same as that of a
,ie, the base address of the array.(Note again the difference between base address of an array and address of an array.So after the cast and assignment in the above statement,followed by the decrement in printf()
, ptr
now gives the memory location right after the last element of the array, which is 5
.
1 2 3 4 5
^ // ^ stands at location of 5, so *ptr gives 5
So when you dereference the pointer ptr
after decrementing it as *(ptr-1)
it prints the value of 5
as expected.
Now finally, contrast it with the second case where 1
is printed.Look at the illustration I have given using the symbol ^. When you had incremented a
as a+1
, it points to the second element of the array, ie 2
and you had assigned this address to ptr
.So when you decrement ptr
it as (ptr-1)
, it jumps back one element and now points to the first element of the array ,ie 1
.So dereferencing ptr
in second case gives 1
.
1 2 3 4 5
^ // ^ stands at address of 1, so *ptr gives 1
Hope this made it all clear.