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

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


当前回答

按照字面意思回答问题。x==x并不总是正确的

double zero = 0.0;
double a[] = { 0,0,0,0,0, zero/zero}; // NaN
cout << (a[5] == 5[a] ? "true" : "false") << endl;

印刷品

false

其他回答

很好的问题/答案。

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

考虑以下声明:

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

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

当然,还有

 ("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[i]
i[a]
*(a+i)

引用数组中元素的方式不同!(一点都不奇怪)

因为避免混淆嵌套非常有用。

你愿意读这个吗

array[array[head].next].prev

或者:

head[array].next[array].prev

顺便说一下,C++对于函数调用具有类似的交换性质。您可以使用成员函数来编写x.f().g(),而不是像在C中那样编写g(f(x))。用查找表替换f和g,您可以编写g[f[x]](函数样式)或(x[f])[g](oop样式)。后者非常适合包含索引的结构:x[xs].y[ys].z[zs]。使用更常见的符号zs[ys[xs[x].y].z]。

在C数组中,arr[3]和3[arr]是相同的,它们的等价指针符号是*(arr+3)到*(3+arr)。但相反,[arr]3或[3]arr不正确,会导致语法错误,因为(arr+3)*和(3+arr)*不是有效表达式。原因是解引用运算符应该放在表达式产生的地址之前,而不是地址之后。