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

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


当前回答

在c编译器中

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

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

其他回答

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

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

不是答案,只是一些思考的食物。如果类具有重载的索引/下标运算符,则表达式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&);
};

我只是发现这种丑陋的语法可能是“有用的”,或者至少当你想处理一个索引数组,这些索引引用了同一个数组中的位置时,使用起来非常有趣。它可以替换嵌套的方括号,使代码更可读!

int a[] = { 2 , 3 , 3 , 2 , 4 };
int s = sizeof a / sizeof *a;  //  s == 5

for(int i = 0 ; i < s ; ++i) {  
           
    cout << a[a[a[i]]] << endl;
    // ... is equivalent to ...
    cout << i[a][a][a] << endl;  // but I prefer this one, it's easier to increase the level of indirection (without loop)
    
}

当然,我很确定在实际代码中没有这样的用例,但我还是觉得很有趣:)

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

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

因此,[5]将评估:

*(a + 5)

并且5[a]将评估:

*(5 + a)

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

在c编译器中

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

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