在C和C ++中通过索引访问数组

所以,有一些面试官喜欢问什么原因这个小技巧:

int arr[] = {1, 2, 3}; 2[arr] = 5; // does this line compile? assert(arr[2] == 5); // does this assertion fail? 

根据我所能理解的, a[b]被转换为*(a + b) ,由于加法是可交换的,所以它们的顺序并不重要,所以2[a]真的是*(2 + a)

这是保证工作的C和/或C + +的规格?

是。 6.5.2.1第1段(C99标准)描述了[]运算符的参数:

其中一个expression式的types应该是“指向对象type指针”,另一个expression式应该是整数types,结果的types是“ type ”。

6.5.2.1第2款(强调增加):

后缀expression式后面跟着方括号[]的expression式,是数组对象元素的下标。 下标运算符[]的定义是E1[E2](*((E1)+(E2))) 。 由于适用于二元运算符的转换规则,如果E1是一个数组对象(等价地,指向一个数组对象的初始元素的指针), E2是一个整数, E1[E2]指定E2E2个元素E1 (从零开始计数)。

它说什么都不要求[]的理由顺序是理智的。

一般情况下2[a]a[2] 2[a]是相同的,并且这在C和C ++中保证是等价的(假设没有运算符重载),因为正如你所说的那样,它翻译成*(2+a)*(a+2) 。 由于加运算符是可交换的,所以这两种forms是等价的。

虽然forms是相同的,为了所有的圣洁(和未来的维护程序员),请select“a [2]”forms。

PS,如果你在采访时被问到了这个问题,请代表C / C ++社区进行确切的报复,并确保你要求面试官列出所有三字母序列作为你给出答案的先决条件。 也许这将使他/她在将来无法提出这样的问题(毫无价值,关于实际编程)。 在面试官实际上知道所有九个三元组序列的情况下,你总是可以再次尝试用虚拟基类的销毁顺序来重写这些问题 – 这个问题在日常编程中同样令人难以置信。