有些面试官出于某种原因喜欢问这个小技巧问题:
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++ 的规范?
有些面试官出于某种原因喜欢问这个小技巧问题:
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 标准)描述了[]
操作员的参数:
其中一个表达式的类型应为“指向对象的指针
type
”,另一个表达式应为整数类型,结果的类型为“type
”。
6.5.2.1 第 2 段(强调添加):
后缀表达式后跟方括号
[]
中的表达式是数组对象元素的下标指定。下标运算符的定义[]
与E1[E2]
相同(*((E1)+(E2)))
。由于适用于二元+
运算符的转换规则,ifE1
是一个数组对象(相当于,一个指向数组对象的初始元素的指针)并且E2
是一个整数,E1[E2]
指定E2
第一个元素E1
(从零开始计数)。
它没有说任何要求论点的顺序[]
是理智的。
通常2[a]
与 相同,a[2]
并且保证在 C 和 C++ 中都是等效的(假设没有运算符重载),因为正如您的意思,它分别转换为*(2+a)
or *(a+2)
。因为加号运算符是可交换的,所以这两种形式是等价的。
尽管这些形式是等价的,但为了所有神圣(以及未来的维护程序员),请更喜欢“a[2]”形式而不是其他形式。
PS,如果你在面试中被问到这个问题,请代表 C/C++ 社区进行准确的报复,并确保你要求面试官列出所有三元组序列作为你给出答案的先决条件。也许这会让他/她在未来不再问这样的(毫无价值,就实际编程任何东西而言)问题。奇怪的是,面试官实际上知道所有九个三元序列,你总是可以再次尝试用一个关于虚拟基类的破坏顺序的问题来扼杀他们——这个问题与日常编程同样令人难以置信。