In C arrays why is this true? a[5] == 5[a]

来源:互联网 发布:r330打印机清零软件 编辑:程序博客网 时间:2024/04/29 06:07

原帖: http://stackoverflow.com/questions/381542/in-c-arrays-why-is-this-true-a5-5a

==============================================================================================================================

As Joel points out in Stack Overflow podcast #34, in C Programming Language (aka: K & R), there is mention of this property of arrays in C: a[5] == 5[a]

Joel says that it's because of pointer arithmetic but I still don't understand. Why does a[5] == 5[a] ?

Edit: The accepted answer is great. For a lower level view of how this works, see the comments section on that answer. There's a phenomenal conversation there about it. (This edit written about the comments available at the time. ie: the first ~16)

==============================================================================================================================

Because a[5] will evaluate to:

*(a + 5)

and 5[a] will evaluate to:

*(5 + a)

and from elementary school math we know those are equal.

This is the direct artifact of arrays behaving as pointers, "a" is a memory address. "a[5]" is the value that's 5elements further from "a". The address of this element is "a + 5". This is equal to offset "a" from "5" elements at the beginning of the address space (5 + a).

==============================================================================================================================

Because array access is defined in terms of pointers. a[i] is defined to mean *(a + i), which is commutative.

==============================================================================================================================

And, of course

 "ABCD"[2] == 2["ABCD"] == 'C'

The main reason for this was that back in the 70's when C was designed, computers didn't have much memory (64KB was a lot), so the C compiler didn't do much syntax checking. Hence "X[Y]" was rather blindly translated into "*(X+Y)"

This also explains the "+=" and "++" syntaxes. Everything in the form "A = B + C" had the same compiled form. But, if B was the same object as A, then an assembly level optimization was available. But the compiler wasn't bright enough to recognize it, so the developer had to (A += C). Similarly, if C was 1, a different assembly level optimization was available, and again the developer had to make it explicit, because the compiler didn't recognize it. (More recently compilers do, so those syntaxes are largely unnecessary these days)

==============================================================================================================================

One thing no-one seems to have mentioned about Dinah's problem with sizeof:

You can only add an integer to a pointer, you can't add two pointers together. That way when adding a pointer to an integer, or an integer to a pointer, the compiler always knows which bit has a size that needs to be taken into account.

==============================================================================================================================

Dinah Why is sizeof() taken into account. I thought the pointer to 'a' is to the beginning of the array (ie: the 0 element). If this is true, you only need *(a + 5). My understanding must be incorrect. What's the correct reason?

In pointer arithmetic, the size of the item pointed to by the pointer is accounted for. So

char *pch = 0;pch++;printf("%p\n", pch);double *pdbl = 0;pdbl++;printf("%p\n", pdbl);

(on my machine) will print

1
8

It's the reason we can subtract two pointers and get the count of items between them rather than the number of bytes between them. It prevents us from having to put sizeof(T) everywhere in our code.

In a lot of ways, you can think of pointer arithmetic as array arithmetic. But I probably shouldn't have said that. :-)

==============================================================================================================================

Nice question/answers.

Just want to point out that C pointers and arrays are not the same, although in this case the difference is not essential.

Consider the following declarations:

int a[10];int* p = a;

In a.out, the symbol a is at an address that's the beginning of the array, and symbol p is at an address where a pointer is stored, and the value of the pointer at that memory location is the beginning of the array.

==============================================================================================================================


==============================================================================================================================


原创粉丝点击