【问题标题】:Accessing arrays by index[array] in C and C++在 C 和 C++ 中通过 index[array] 访问数组
【发布时间】:2011-07-01 16:41:33
【问题描述】:

有些面试官出于某种原因喜欢问这个小技巧问题:

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++ 的规范?

【问题讨论】:

  • 这在Hidden features of C++中被提及。
  • @erickb - 这个问题专门询问这是否是(非常流行的)实现侥幸,或者这是否是标准规定的。
  • 在这种特定情况下,您将收到关于 a 未定义的错误(因为您的声明声明了 arr,而不是 a),但我认为每个人都了解您实际上是什么问...
  • 你甚至可以对字符串指针感到疯狂。 “abcd”[1] 是“b”。或者给你 1["abcd"].

标签: c++ arrays c square-bracket subscript-operator


【解决方案1】:

通常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] 唯一有用的用法)
  • @Chris,我添加了一个附录 re:运算符重载。感谢您的贡献。
  • 在 C++ 中,您还可以通过template<typename T, size_t N> size_t ARRAYSIZE(T (&a)[N]) { return N; } 来防止int *a = /*something*/; ARRAYSIZE(a)
  • @Logan Capaldo - 我没有说这是一个适当的用途,只是说它是一个一个用途。 :P 在其他情况下,您可能希望明确避免调用类的潜在 operator[] 并且只对 T*T[] 类型的变量进行操作,尽管这很快就会转向人为的示例王国。
  • @Chris,我只是指出其他选项,以防有人跑去更改他们所有的 countof 宏;)。您的优势在于无需更改即可在 C 和 C++ 中工作,并在 C++ 中获得额外功能。
【解决方案2】:

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

其中一个表达式的类型应为“指向对象type”的类型,另一个表达式应为整数类型,结果的类型为“type”。

6.5.2.1 第 2 段(强调添加):

后缀表达式后跟方括号中的表达式 [] 是下标 指定数组对象的元素。 下标运算符[]的定义 是E1[E2](*((E1)+(E2))) 相同。由于转换规则 适用于二元 + 运算符,如果 E1 是一个数组对象(等效于指向 数组对象的初始元素)和E2 是一个整数,E1[E2] 指定E2-th E1 的元素(从零开始计数)。

它没有说明要求[] 的参数顺序是理智的。

【讨论】:

  • @Chris - 这如何扩展到多维数组?你能用同样的技巧来迷惑别人吗? (或者我应该因为行和列的主要扭曲而问一个新问题?)
  • @jww - 不完全是。你可以做3[x][2],但你不能做3[2][x]——它相当于*(*(3 + 2) + x),你会取消引用integer 5,这几乎肯定是坏的。
  • 好吧,它将操作数命名为 E1 和 E2,然后只讨论 E1 是一个数组。在我的书中,它建立了论点的顺序。
猜你喜欢
  • 2021-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 2012-06-09
  • 2015-01-10
  • 2014-12-29
相关资源
最近更新 更多