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

Nul*_*ion 36 c c++ arrays square-bracket

有一个小技巧问题,一些采访者喜欢问什么原因:

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

根据我的理解,a[b]转换为*(a + b)并且因为加法是可交换的,所以它们的顺序并不重要,所以2[a]它确实*(2 + a)很好.

这可以保证按C和/或C++的规格工作吗?

Chr*_*utz 35

是.6.5.2.1第1段(C99标准)描述了[]运营商的论据:

其中一个表达式应具有"指向对象的指针type",另一个表达式应具有整数类型,结果的类型为" type".

6.5.2.1第2段(重点补充):

post fi x表达式后跟方括号中的表达式[]是数组对象元素的下标.下标操作符的定义[]E1[E2]相同(*((E1)+(E2))).由于适用于二元+运算符的转换规则,if E1是一个数组对象(等效地,指向数组对象的初始元素的指针)并且E2是一个整数,因此E1[E2]指定E2-th元素E1(从零开始计数).

它说什么都不需要论证的顺序[]是理智的.

  • @Chris - 这如何扩展到多维数组?你能用同样的技巧来迷惑人们吗?(或者我应该因为行和列的主要扭曲而提出一个新问题吗?) (2认同)
  • @jww - 不完全是。你可以做 `3[x][2]`,但你不能做 `3[2][x]` - 它等价于 `*(*(3 + 2) + x)`,你会取消引用`int`eger 5,这几乎肯定是不好的。 (2认同)

Mic*_*eyn 24

通常2[a]是相同的,a[2]并且保证在C和C++中都是等效的(假设没有运算符重载),因为你的意思是它分别转换为*(2+a)*(a+2).因为加号运算符是可交换的,所以这两种形式是等价的.

虽然形式是等价的,但为了所有神圣的(以及未来的维护程序员),请选择"a [2]"形式而不是另一种形式.

PS,如果你在面试时被问到这个问题,请代表C/C++社区进行报复,并确保你要求面试官列出所有三字母序列作为你给出答案的先决条件.也许这将使他/她对将来要求这样的(毫无价值,关于实际编程任何事情)问题感到沮丧.在面试官实际上知道所有九个三字母序列的奇怪事件中,你总是可以再次尝试用虚拟基类的破坏顺序来解释它们 - 这个问题就像日常编程一样令人难以置信.

  • +1但在C++中你可以使用`#define ARRAY_SIZE(a)(sizeof(a)/ sizeof(0 [a]))`作为一个宏来查找一个不会(并且不能用于)为`std :: vector`和重载`[]`运算符的类型工作 - 这不能阻止`int*a =/*something*/; ARRAY_SIZE(a)`但对其他任何东西都可以非常安全.(这是'0 [a]`我见过的唯一有用的用途 (3认同)
  • 在 C++ 中,您还可以 `template<typename T, size_t N> size_t ARRAYSIZE(T (&a)[N]) { return N; }` 确实会阻止 `int *a = /*something*/; 数组大小(a)`。 (2认同)