【发布时间】:2019-09-09 10:34:51
【问题描述】:
有人告诉我,编译器会在必要时将数组名称转换为指向数组第一个元素的指针。所以我用这个规则解决了很多问题,直到我看到这个都很好。
int main()
{
int a[2][3] = {{1,2,3}, {5,6,7}}, (*p)[3];
p = a[0];
for(int i = 0; i < 3; i++)
printf("%d", (*p)[i]);
}
输出是123,带有代码块。
我试图解决它:
(*p)[i]) 应与*((*p)+i)....(1) 相同
正如规则所说,“数组名称被转换为指向数组第一个元素的指针”。我将第二条指令p=a[0] 转换为p=&a[0][0] (因为a[0] 是一个子-数组名称,其第一个元素是a[0][0])。 所以(*p) 可以写成(*(&a[0][0]))。与a[0][0] 相同。所以 eqn (1) 变成了
*(a[0][0]+i).
这就是我卡住的地方。 a[0][0]+i 是一个元素而不是地址。所以对它应用* 操作符是无效的。但我也在原始代码中用p=&a[0][0]; 替换了声明p=a[0];,答案保持不变。我也将其替换为p=&a[0];。答案还是一样。现在我超级困惑。
【问题讨论】:
-
如果你编译程序,你将有得到类似 warning: assignment from incompatible pointer type [-Wincompatible-pointer-types] p=a[ 0] ;,这就解释了为什么它没有意义。
-
你被教导正确C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) --- 你的实现是错误的,而不是
p=a;。启用编译器警告(-Wall -Wextra -pedantic用于 gcc/clang)和(/W3用于 VS)并且在编译没有警告之前不要接受代码。a[0]是int *,但是p是int (*)[3]。由于a将衰减为指向访问时第一个元素的指针(即3 int 的数组),a与p兼容,而不是a[0]。 -
@AnttiHaapala 是的,它产生了警告。但是为什么这不是编译错误?这是否意味着编译器已经自行将其转换为兼容类型?如果这个代码是在笔试中给我的,我应该将错误标记为我的正确选项吗?
-
不是编译错误,因为the C standard explicitly allows a compiler to successfully compile an invalid program, provided that required diagnostics are issued。这是为了允许使用 C 编译器来编译 1970 年代以来的各种 b0rken 代码等等......
-
太棒了,学习已经发生了——这让今天很美好......
标签: c pointers multidimensional-array array-formulas pointer-arithmetic