正如Joel在Stack Overflow播客#34中指出的,在C编程语言(又名:K&R)中,提到了C:a[5]==5[a]中数组的这个属性

乔尔说这是因为指针运算,但我仍然不明白。为什么a[5]==5[a]?


当前回答

当然,还有

 ("ABCD"[2] == 2["ABCD"]) && (2["ABCD"] == 'C') && ("ABCD"[2] == 'C')

其主要原因是,在70年代设计C时,计算机没有太多内存(64KB是很多),因此C编译器没有做太多语法检查。因此,“X[Y]”相当盲目地翻译为“*(X+Y)”

这也解释了“+=”和“++”语法。“A=B+C”形式的所有对象都具有相同的编译形式。但是,如果B是与A相同的对象,则可以进行汇编级优化。但是编译器不够明亮,无法识别它,所以开发人员不得不(A+=C)。类似地,如果C为1,则可以使用不同的汇编级优化,开发人员再次必须使其显式,因为编译器无法识别它

其他回答

C标准对[]运算符的定义如下:

a[b]==*(a+b)

因此,[5]将评估:

*(a + 5)

并且5[a]将评估:

*(5 + a)

a是指向数组的第一个元素的指针。a[5]是距离a更远的5个元素的值,与*(a+5)相同,从小学数学中我们知道它们是相等的(加法是可交换的)。

C基于BCPL。BCPL将存储器直接暴露为一系列可寻址字。一元运算符!X(也称为LV)为您提供了地址位置X的内容。为了方便起见,还有一个二进制运算符X!Y等于!(X+Y),它为您提供了位置X处数组的第Y个字的内容,或者等效地,位置Y处数组的X个字。

在C,X!Y变成了X[Y],但是!的原始BCPL语义!(X+Y)表示通过,这解释了为什么算子是可交换的。

因为C编译器总是将数组表示法转换为指针表示法。a[5]=*(a+5)也是5[a]=*所以,两者都是相等的。

很好的问题/答案。

我只想指出,C指针和数组并不相同,尽管在这种情况下,差异并不是本质的。

考虑以下声明:

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

在a.out中,符号a位于数组开始的地址,符号p位于存储指针的地址,指针在该内存位置的值是数组的开始。

对于C中的指针,我们有

a[5] == *(a + 5)

而且

5[a] == *(5 + a)

因此,a[5]==5[a]是正确的。