Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C array address confusion

Tags:

arrays

c

pointers

Say we have the following code:

int main(){
    int a[3]={1,2,3};
    printf("      E: 0x%x\n", a);
    printf("  &E[2]: 0x%x\n", &a[2]);
    printf("&E[2]-E: 0x%x\n", &a[2] - a);
    return 1;
}

When compiled and run the results are follows:

      E: 0xbf8231f8
  &E[2]: 0xbf823200
&E[2]-E: 0x2

I understand the result of &E[2] which is 8 plus the array's address, since indexed by 2 and of type int (4 bytes on my 32-bit system), but I can't figure out why the last line is 2 instead of 8?

In addition, what type of the last line should be - an integer or an integer pointer?

I wonder if it is the C type system (kinda casting) that make this quirk?

like image 670
Pwn Avatar asked Apr 29 '09 08:04

Pwn


3 Answers

You have to remember what the expression a[2] really means. It is exactly equivalent to *(a+2). So much so, that it is perfectly legal to write 2[a] instead, with identical effect.

For that to work and make sense, pointer arithmetic takes into account the type of the thing pointed at. But that is taken care of behind the scenes. You get to simply use natural offsets into your arrays, and all the details just work out.

The same logic applies to pointer differences, which explains your result of 2.

Under the hood, in your example the index is multiplied by sizeof(int) to get a byte offset which is added to the base address of the array. You expose that detail in your two prints of the addresses.

like image 163
RBerteig Avatar answered Oct 20 '22 15:10

RBerteig


When subtracting pointers of the same type the result is number of elements and not number of bytes. This is by design so that you can easily index arrays of any type. If you want number of bytes - cast the addresses to char*.

like image 40
sharptooth Avatar answered Oct 20 '22 17:10

sharptooth


When you increment the pointer by 1 (p+1) then pointer would points to next valid address by adding ( p + sizeof(Type)) bytes to p. (if Type is int then p+sizeof(int))

Similar logic holds good for p-1 also ( of course subtract in this case).

If you just apply those principles here:

In simple terms:

a[2] can be represented as (a+2)
a[2]-a      ==>  (a+2) - (a)    ==> 2

So, behind the scene,

a[2] - a[0]  
==> {(a+ (2* sizeof(int)) ) - (a+0) }  / sizeof(int) 
==> 2 * sizeof(int) / sizeof(int) ==> 2
like image 43
aJ. Avatar answered Oct 20 '22 17:10

aJ.