Since you seem to be completely new to this, let me explain it to you in simple words, and not look for strict explanations.
You see that for your program above, a and &a will have the same numerical value , and I believe that where all your confusion is. You might think that if they are in the following case, after a should indicate the following address , following the arithmetic of pointers:
(&a+1) and (a+1)
But this is not so! The base address of the array ( a here) and the address of the array are not the same! a and &a may be the same numerically, but they do not match the type . a is of type char* , while &a is of type char (*)[5] , i.e. &a is a pointer to (address) and an array of size 5.But a , as you know, this is the address of the first element of the array . Numbered they are the same as you can see in the illustration using ^ below.
But when you increment these two pointers / addresses, i.e. like (a+1) and (&a+1) , arithmetic is completely different. In the first case, it “jumps” to the address of the next element in the array, in the latter case, it jumps to 5 elements, since the size of the array is 5 elements! . Get it now?
1 2 3 4 5 ^
The following is an error about an undefined array binding, since an explicit indication of the size is not indicated explicitly, since the program does not know how many elements "jumps" when something like (& a + 1) is encountered.
char a[]={1,2,3,4,5}; char *ptr=(char *)(&a+1);
Now to the part where you reduce pointers / addresses like (ptr-1) . In the first case, before you go to the decrement part, you should know what happens in the higher output, where it is cast to input char* :
char *ptr=(char *)(&a+1);
What happens here is that you “disconnect” the original type from (&a+1) , which was type char (*)[5] , and now type it in to enter char* , which matches type a , then yes, the base address of the array. (Pay attention to the difference between the base address of the array and the address of the array . Thus, after the act and assignment in the above description by decree in printf() , ptr now gives a memory cell immediately after the last element of the array, which is 5 .
1 2 3 4 5 ^
So, when you play the ptr after decreasing it as *(ptr-1) , it prints the value 5 as expected.
Now finally compare it to the second case when 1 is printed. Look at the illustration I gave with the ^ symbol. When you incremented a as a+1 , it points to the second element of the array, i.e. 2 , and you assigned that address ptr . Therefore, when you reduce ptr by (ptr-1) , it jumps back one element and now points to the first element of the array, i.e. 1 . So dereferencing ptr in the second case gives 1 .
1 2 3 4 5 ^
Hope this is all clear.