C语言原生数组索引的奇怪写法

 
Category: C_C++

写在前面

最近逛知乎发现一个有意思的C++表达式:

[arr](){0;return 0;}()[arr]

乍一看觉得不能编译通过, 后来一想这不是C++11新增的Lambda表达式么?

对于这个写法, 相当于先创建了一个lambda匿名函数, 然后直接调用, 并且取值, 但是这里的取值就显得很奇怪了, 因为这意味着对于一个(C风格的)数组, 可以通过下面的方法进行下标取值:

i[arr]

为什么也可以这样取值呢?

下面来看一段测试代码:

#include <iostream>
#include <vector>

using namespace std;
const int SIZE = 5;

int main(int argc, char const *argv[]) {
    int arr[SIZE] = {1, 2, 3};
    // vector<int> arr{1, 2, 3}; // error
    for (int i = 0; i < SIZE; ++i) cout << i[arr] << " " << arr[i] << endl;
    cout <<
        [arr]() {
            0;
            return 0;
        }()[arr]
         << endl;
    return 0;
}

可以发现arr[i]i[arr]两者没有区别.

C数组索引

后来看到一篇回答1:

In declaration, no. When you use pointer variables, yes: x[y] is identical to *(x + y). So a[1] is the same as *(a + 1), which is the same as *(1 + a), which is again the same as 1[a] (but please don’t use this last one).

也就是说, 因为数组变量名即为首地址(指针), 所以在i位置取值(arr[i])用指针表示法可以表达为*(arr+i), 那么因为加法交换律, *(i+arr)就也是可以的, 那么这样对应一下, 就得到i[arr]也是可以的.

虽然有点离谱, 但是这确实是可以的 (只不过最好不要在你的代码中这样写).

ref