0
int a[10][5];
for (int i = 0; i < 10; i++)
{
    for (int j = 0; j < 10; j++)
    {
        cout << i[j[a]];
        cout << j[i[a]];
    }
}  

编辑:假设值已经初始化为数组,那么这个 cout 有效吗?

请仅解释该i[j[a]];部分,而不管我只关心该声明的程序!

4

3 回答 3

1
cout << i[j[a]];
cout << j[i[a]];

在 C++ 中,该X[Y]符号在词法上等价于*(X+Y)

[C++11: 5.2.1/1]: [..]该表达式E1[E2](根据定义)与*((E1)+(E2)) [..]

这意味着Y[X]等价于,*(Y+X)这与加法是可交换的 相同。*(X+Y)

出于某种原因,作者决定通过编写这个令人困惑的代码来尝试“聪明”。

通过交换律和X[Y]单独的定义:

i[j[a]] => i[*(j+a)] => *(i+*(j+a)) => *(*(a+j)+i) => *(a[j] + i) => a[j][i]
j[i[a]] => j[*(i+a)] => *(j+*(i+a)) => *(*(a+i)+j) => *(a[i] + j) => a[i][j]

那么,您的cout陈述相当于:

cout << a[j][i];
cout << a[i][j];

在任何情况下,循环都会尝试读取数组边界,因为数组5的每个元素中只有整数a,而您的内部循环会尝试一直到10.

其实际结果是不确定的,因此您可能会获得无声的成功、无声的失败、任意值、分段错误、断电、黑洞、圣诞节的小马、脚趾截肢或新自行车。

即使循环条件固定,请注意第一个语句在语义上是不正确的(假设您继续将第一个维度归因于外部循环,将第二个维度归因于内部循环)。

于 2013-01-17T17:47:37.747 回答
0

C 数组有一个奇怪的怪癖,允许通过“相反”方向访问它们。这深深植根于数组的指针算法。例如,a[1]等价于*(a + 1)。同样,1[a]等价于*(1 + a)。由于加法的交换性质,这非常有效。更多细节可以在这里找到。

有了这些知识,表达i[j[a]]可以分为两个不同的部分。由于您拥有的数组的多维性质,j[a]相当于which 将返回另一个数组,例如,我们将调用此返回的数组。然后你就有了相当于. 将它们重新组合在一起会告诉你这相当于. 实际上,这意味着这只是一种混淆的书写方式。*(j + a)pi[p]*(i + p)i[j[a]]*(i + *(j + a))i[j[a]]a[j][i]

于 2012-09-09T04:29:29.420 回答
0

在 C/C++ 中,可以用整数索引为指针下标,也可以用指针为整数索引下标,含义(语义)完全相同。我不知道为什么疯狂的语法是有效的,但它确实如此,而且显然它会永远存在。

#include <stdio.h>

int main(int argc, char** argv)
{
  int i = 1, array[10];
  printf("%ld\n", &(i[array])-&(array[i]));
  return 0;
}

输出:

0
于 2012-09-09T05:02:57.060 回答