正如Joel在Stack Overflow播客#34中指出的,在C编程语言(又名:K&R)中,提到了C:a[5]==5[a]中数组的这个属性
乔尔说这是因为指针运算,但我仍然不明白。为什么a[5]==5[a]?
正如Joel在Stack Overflow播客#34中指出的,在C编程语言(又名:K&R)中,提到了C:a[5]==5[a]中数组的这个属性
乔尔说这是因为指针运算,但我仍然不明白。为什么a[5]==5[a]?
当前回答
嗯,这是一个只有语言支持才能实现的功能。
编译器将a[i]解释为*(a+i),表达式5[a]的计算结果为*(5+a)。由于加法是可交换的,结果证明两者相等。因此,表达式的计算结果为true。
其他回答
嗯,这是一个只有语言支持才能实现的功能。
编译器将a[i]解释为*(a+i),表达式5[a]的计算结果为*(5+a)。由于加法是可交换的,结果证明两者相等。因此,表达式的计算结果为true。
按照字面意思回答问题。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编译器总是将数组表示法转换为指针表示法。a[5]=*(a+5)也是5[a]=*所以,两者都是相等的。
现在有点历史了。在其他语言中,BCPL对C的早期发展产生了相当大的影响。如果您在BCPL中声明的数组类似于:
let V = vec 10
实际上分配了11个字的内存,而不是10个。通常V是第一个,并包含紧接其后的单词的地址。因此,与C不同,命名V到那个位置,并获取数组第0个元素的地址。因此,BCPL中的数组间接寻址表示为
let J = V!5
真的不得不做J=!(V+5)(使用BCPL语法),因为需要获取V以获得阵列的基地址。因此,V!5和5!V是同义词。据坊间观察,WAFL(Warwick Functional Language,沃里克函数语言)是用BCPL编写的,据我所知,在访问用作数据存储的节点时,倾向于使用后一种语法而不是前一种语法。当然这是35到40年前的某个地方,所以我的记忆有点生疏
省去了额外的存储字,并在命名数组时让编译器插入数组的基地址,这一创新是后来才出现的。根据C历史论文,这大约发生在C中添加结构的时候。
注意!BCPL中既有一元前缀运算符,也有二元中缀运算符,在这两种情况下都是间接操作。只是二进制形式在执行间接操作之前包括两个操作数的相加。鉴于BCPL(和B)面向单词的性质,这实际上很有意义。当C获得数据类型时,“指针和整数”的限制就变得必要了,sizeof也成了一件事。
因为避免混淆嵌套非常有用。
你愿意读这个吗
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]。