tags:

views:

644

answers:

9

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?

+8  A: 

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*.

sharptooth
+4  A: 

The line &E[2]-2 is doing pointer subtraction, not integer subtraction. Pointer subtraction (when both pointers point to data of the same type) returns the difference of the addresses in divided by the size of the type they point to. The return value is an int.

To answer your "update" question, once again pointer arithmetic (this time pointer addition) is being performed. It's done this way in C to make it easier to "index" a chunk of contiguous data pointed to by the pointer.

marcog
The return value is an int, not an int*.
paxdiablo
Sorry, blonde moment...you're right.
marcog
A: 

That's hexidecimal 20, or decimal 32. Never mind, I misread the result.

Anonymous
+2  A: 

You may be interested in Pointer Arithmetic In C question and answers.

basically, + and - operators take element size into account when used on pointers.

mouviciel
A: 

If you want to see the byte difference, you'll have to a type that is 1 byte in size, like this:

printf("&E[2]-E:\t0x%x\n",(char*)(&a[2])-(char*)(&a[0]))
schnaader
+1  A: 

When adding and subtracting pointers in C, you use the size of the data type rather than absolute addresses.

If you have an int pointer and add the number 2 to it, it will advance 2 * sizeof(int). In the same manner, if you subtract two int pointers, you will get the result in units of sizeof(int) rather than the difference of the absolute addresses.

(Having pointers using the size of the data type is quite convenient, so that you for example can simply use p++ instead of having to specify the size of the type every time: p+=sizeof(int).)

Guffa
+5  A: 

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
aJ
+7  A: 

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.

RBerteig
+1  A: 

Re: "In addtion,what type of the last line should be?An integer,or a integer pointer??"

an integer/number. by the same token that the: Today - April 1 = number. not date

Michael Buen
elegant indeed.
yfel