starting address of array a and &a

前端 未结 5 1276
我在风中等你
我在风中等你 2021-02-03 14:03

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

相关标签:
5条回答
  • 2021-02-03 14:09

    The difference is in the type of the pointer that you get:

    • Array name a by itself represents a pointer to the initial element of the array. When interpreted in that way, e.g. in an expression a+1, the pointer is considered to point to a single 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 the pointer is moved is determined by the type of the object pointer to by the pointer. In case the pointer points to char, adding N advances the pointer by N bytes. In case the pointer points to an array of five chars, adding N advances the pointer by 5*N bytes.

    That's precisely the difference that you are getting: your first example advances the pointer to the element one past the end of the array (which is legal), and then move it back to the last element. Your second example, on the other hand, advances the pointer to the second element, and then moves it back to point to the initial element of the array.

    0 讨论(0)
  • 2021-02-03 14:20

    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.

    0 讨论(0)
  • 2021-02-03 14:20

    Arrays aren't pointers! Read section 6 of the comp.lang.c FAQ for more information.

    Let's look at your second case first, since it's the more "normal" and idiomatic looking. Line by line:

    1. You declare an array a containing 5 char elements.
    2. The name of the array (a) decays into a pointer to its first element in this context. You add 1 to that and assign the result to ptr. ptr points to the 2. No cast is necessary, though you have one.
    3. You subtract 1 from ptr and then dereference and print - hence you get the 1.

    Now, let's address the first case, again line by line:

    1. You declare an array a containing 5 char elements.
    2. You take the address of a, yielding a char (*)[5] type pointer. You then add 1 to this pointer - because of pointer arithmetic this new pointer pasts to the byte just after 5 in memory. Then you typecast (required, this time) and assign this value to ptr.
    3. You subtract 1 from ptr and then dreference and print. ptr is a char *, so this subtraction simply moves the pointer back by one from "one past the end of a" to point to the last element of a. Hence you get the 5.

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

    0 讨论(0)
  • 2021-02-03 14:25

    What you are running into is a subtlety of pointer arithmetic.

    The compiler treats "a" as a pointer to char - an entity that is 1 byte in size. Adding 1 to this yields a pointer that is incremented by the size of the entity (i.e. 1).

    The compiler treats "&a" as a pointer to an array of chars - an entity that is 5 bytes in size. Adding 1 to this yields a pointer that is incremented by the size of the entity (i.e. 5).

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

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

    0 讨论(0)
  • 2021-02-03 14:25

    Arrays "decay" into pointers to the first element. So taking the address of a gives you a pointer to an array of 5 chars, which is like declaring a char[][5]. And incrementing this pointer advances to the next element of the char[][5] array - that is 5 characters at a time. This is different from incrementing the pointer that decays from the char[5] array - that is, one character at a time.

    0 讨论(0)
提交回复
热议问题