为啥这行得通?不合逻辑的数组访问

Posted

技术标签:

【中文标题】为啥这行得通?不合逻辑的数组访问【英文标题】:Why does this work? Illogical array access为什么这行得通?不合逻辑的数组访问 【发布时间】:2012-02-13 05:07:57 【问题描述】:

我的一个朋友第一次学习C++,给我发了这个sn-p:

int foo[] =  3, 38, 38, 0, 19, 21, 3, 11, 19, 42 ;
char bar[] = " abcdefghijklmnopqrstuvwxyz01234567890+-,.!?-_";
for (int i = 0; i < 10; ++i) 
  std::cout << foo[i][bar];

乍一看,我告诉他这不起作用 - 我认为它不会编译,或者至少会导致访问冲突,因为 foo 不是二维数组,他回答说有。

我自己尝试过,令我惊讶的是,sn-p 运行得非常好。问题是:为什么?

根据逻辑、常识和良好实践,语法应该是bar[foo[i]]

我很惭愧地承认我不知道发生了什么。在这种情况下,foo[i][bar] 的有效语法是什么?

【问题讨论】:

这不是完全重复的,答案很有趣。这两个问题的根本原因是相同的,但 *** 上的数百个问题都是如此。 顺便说一句:如果我会做这些事情,我只会同意输出...... 有趣的是,如果您阅读了链接的问题,这实际上是有道理的,但仍然与您不理解它时一样不合逻辑;不合逻辑的部分只是从“这是如何工作的”转变为“他们为什么让这个工作”。 这与其说是语法问题,不如说是语义问题。 【参考方案1】:

简单来说,在 C 中(以及在 C++ 中,当 [] 未重载时)对数组元素的访问如下:

x[i] = *(x + i)

所以,有了这个和一点算术......

  foo[i][bar]
= (foo[i])[bar]
= (*(foo + i))[bar]
= *((*(foo + i)) + bar)
= *(bar + (*(foo + i)))
= bar[*(foo + i)]
= bar[foo[i]]

但不要使用这个“事实”。如您所见,它使代码不可读,不可读的代码是不可维护的。

【讨论】:

另外,我们可以概括一下:foo[x][y][z] = z[y[x[foo]]], demo 这是一个简短的证明:foo[i][bar] = (foo[i])[bar] = *(foo[i] + bar) = *(bar + foo[i]) = bar[foo[i]]

以上是关于为啥这行得通?不合逻辑的数组访问的主要内容,如果未能解决你的问题,请参考以下文章

为啥我可以从 初始化常规数组,而不是 std::array

为啥 IEEE-754 决定 NaN != NaN 尽管不合逻辑?

为啥这两个 char 数组不相等?

为啥这个非常简单的 C# 方法会产生如此不合逻辑的 CIL 代码?

为啥这行得通?方法重载+方法覆盖+多态

为啥这行得通(不使用与使用选项)?