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]];
部分,无论我只关注该声明的程序如何!
答案 0 :(得分:1)
cout << i[j[a]];
cout << j[i[a]];
在C ++中,X[Y]
符号词法等同于*(X+Y)
:
[C++11: 5.2.1/1]:
[...] 表达式E1[E2]
与*((E1)+(E2))
[...] <相同(按定义) / p>
这意味着Y[X]
相当于*(Y+X)
,与addition is commutative后的*(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
。
这个的实际结果是不确定的,所以你可以获得沉默的成功,无声的失败,任意的价值,分段错误,停电,黑洞,圣诞节的小马,脚趾截肢或新的自行车。 / p>
即使循环条件是固定的,请注意第一个语句在语义上是不正确的(假设您继续将第一个维度归因于外部循环而第二个维度归因于内部循环)。
答案 1 :(得分:0)
C数组有一个奇怪的怪癖,允许它们通过“相反”方向访问。这深深植根于数组的指针算法。例如,a[1]
相当于*(a + 1)
。同样,1[a]
相当于*(1 + a)
。由于添加的交换性质,这非常好。可以找到更多详细信息here。
凭借这些知识,表达式i[j[a]]
可以分为两个不同的部分。 j[a]
等同于*(j + a)
,由于您拥有的数组具有多维特性,它将返回另一个数组,例如我们将调用此返回的数组p
。然后你有i[p]
语句,它等同于*(i + p)
。将它全部带回来会向您显示i[j[a]]
相当于*(i + *(j + a))
。实际上,这意味着i[j[a]]
只是一种模糊的写作方式a[j][i]
。
答案 2 :(得分: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