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

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


当前回答

很好的问题/答案。

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

考虑以下声明:

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

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

其他回答

In C

 int a[]={10,20,30,40,50};
 int *p=a;
 printf("%d\n",*p++);//output will be 10
 printf("%d\n",*a++);//will give an error

指针p是“变量”,数组名称a是“助记符”或“同义词”,因此p++有效,而a++无效。

a[2]等于2[a],因为这两者的内部运算都是“指针算术”,内部计算为*(a+2)等于*(2+a)

对于C中的指针,我们有

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

而且

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

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

不是答案,只是一些思考的食物。如果类具有重载的索引/下标运算符,则表达式0[x]将不起作用:

class Sub
{
public:
    int operator [](size_t nIndex)
    {
        return 0;
    }   
};

int main()
{
    Sub s;
    s[0];
    0[s]; // ERROR 
}

由于我们无法访问int类,因此无法执行此操作:

class int
{
   int operator[](const Sub&);
};

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

你愿意读这个吗

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编译器中

a[i]
i[a]
*(a+i)

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