此 COUT 语句将如何运行

how will this cout statement run

本文关键字:运行 何运行 COUT 语句      更新时间:2023-10-16
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]];部分,不管程序如何,我只关心这个陈述!

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

这样做的实际结果是不确定的,所以你可能会得到无声的成功、无声的失败、任意值、分割错误、停电、黑洞、圣诞节的小马、脚趾截肢或新自行车。

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

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

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

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

#include <stdio.h>
int main(int argc, char** argv)
{
  int i = 1, array[10];
  printf("%ldn", &(i[array])-&(array[i]));
  return 0;
}

输出:

0