The starting address of the array a and &

The next two lines

char a[5]={1,2,3,4,5}; char *ptr=(char *)(&a+1); printf("%d",*(ptr-1)); 

This displays 5 on the screen. If used instead of a and

 char a[5]={1,2,3,4,5}; char *ptr=(char *)(a+1); printf("%d",*(ptr-1)); 

Fingerprint 1

Both a and & a are the starting address of the array. So why is this difference?

Also char * ptr = & a + 1;

shows a warning.

+7
source share
5 answers

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 ^ // ^ 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 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); //(&a+1) gives error as array size not specified. 

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 ^ // ^ stands at location of 5, so *ptr gives 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 ^ // ^ stands at address of 1, so *ptr gives 1 

Hope this is all clear.

+9
source

Arrays are not pointers! For more information, read section 6 of the Frequently Asked Questions comp.lang.c.

First, look at your second case, as it is more “normal” and idiomatic. Line by line:

  • You declare an array a containing 5 char elements.
  • The name of the array ( a ) splits into a pointer to its first element in this context. You add 1 to it and assign the result to ptr . ptr points to 2 . No throw is needed, although you have one.
  • You subtract 1 from ptr and then play and print - hence you get 1 .

Now let me turn to the first case, again in turn:

  • You declare an array a containing 5 char elements.
  • You take address a , giving way to a pointer of type char (*)[5] . Then you add 1 to this pointer - due to the arithmetic of the pointer, this new pointer goes to the byte immediately after 5 in memory. Then you create (required, this time) and assign this value to ptr .
  • You subtract 1 from ptr and then dreference and print. ptr is a char * , so this subtraction just moves the pointer back to one of "one after the end of a " to point to the last element of a . Therefore, you get 5 .

Finally, the reason char *ptr=&a+1; gives a warning because C requires conversions between pointer types in order to have an explicit cast. As mentioned above, &a is of type char (*)[5] , not char * , so you need an explicit conversion to assign this value to char * .

+12
source

The difference lies in the type of pointer you get:

  • The name of the array a itself is a pointer to the source element of the array. When interpreted in this way, for example, in the expression a+1 , it is assumed that the pointer points to one character.
  • When you take &a , on the other hand, the pointer points to an array of five characters.

When you add an integer to a pointer, the number of bytes that the pointer moves is determined by the type of the object pointer by the pointer. If the pointer points to char , appending N advances the pointer to N bytes. If the pointer points to an array of five char s, adding N advances the pointer to 5*N bytes.

This is exactly the difference you get: your first example advances a pointer to an element that is located at the end of the array (which is legal), and then translates it back to the last element. On the other hand, your second example advances the pointer to the second element and then returns it back to the original element of the array.

+2
source

Arrays "decay" into pointers to the first element. Therefore, taking address a, you get a pointer to an array of 5 characters, which looks like a char[][5] declaration. The increment of this pointer goes to the next element of the char[][5] array - 5 characters at a time. This differs from a pointer increment, which splits into a char[5] array, that is, one character at a time.

0
source

What you use is the subtlety of pointer arithmetic.

The compiler treats "a" as a pointer to a char - an entity of size 1 byte. Adding 1 to this gives a pointer that increases by the size of the object (i.e. 1).

The compiler considers "& a" as a pointer to an array of characters - an entity of 5 bytes in size. Adding 1 to this gives a pointer that increases by the size of the object (i.e. 5).

This is how pointer arithmetic works. Adding one to a pointer increases it by the size of the type that it is a pointer.

The funny thing, of course, is that when it comes to evaluating the value of "a" or "& a", when dereferencing, they both evaluate at the same address. That is why you see the meanings that you make.

0
source

All Articles