为什么以下代码会生成正确的输出。理想情况下,我们应该通过a
而不是&a
。但我发现传递&a
也会产生相同的结果。但是这对整数变量不起作用,它只适用于数组。有人可以解释它背后的逻辑。提前谢谢。
#include <stdio.h>
void m(int *p)
{
int i = 0;
for(i = 0;i < 3; i++)
printf("%d\t", p[i]);
}
void main()
{
int a[3] = {6, 5, 3};
m(&a);
}
答案 0 :(得分:1)
要回答实际问题,&#34;为什么会这样?&#34;,这是一个简短的答案。首先,您需要查看关联的问题,以了解int *p
,int a[3]
和&a
是什么以及错误原因。然后他们工作的原因:
遗产原因!
在标准化之前,在70年代和80年代,许多旧的编译器并不关心这种代码。地址是一个地址,谁在乎类型是否有点错误,对吧?因此编写了大量代码,其中包含这样的代码,这在现行标准中是错误的,但在逻辑上&#34; (通过人类思考)应该工作。
因此,当C标准化时,这种代码只是被定义为具有未定义的行为,而不是使这种代码不可编译。问题解决了。
因此,在构建现代代码时始终启用警告并修复它们。这不会捕获所有C未定义行为,但它会捕获很多,包括这个。
答案 1 :(得分:1)
我很确定这是未定义的行为。首先,您可以在编译器上获得警告的示例:
main.cpp: In function 'main':
main.cpp:11:5: warning: passing argument 1 of 'm' from incompatible pointer type
m(&a);
^
main.cpp:2:6: note: expected 'int *' but argument is of type 'int (*)[3]'
void m(int *p)
C11标准(n1570)说:
§6.7.6.2/ 2要使两个指针类型兼容,两者都应该是 具有相同的资格,两者都是兼容类型的指针。
§J.2/ 1在以下情况下,行为未定义:
- 出现在a之外的“应该”或“不应该”的要求 违反了约束条款(第4条)。
[..]
- 不需要兼容的两种指针类型 相同的限定条件,或者不是兼容类型的指针 (6.7.6.1)。
答案 2 :(得分:0)
a是数组的起始地址。所以你不需要尊重地址。
替换你的行:
m(&a);
与
m(a);