为什么以下代码有效?

时间:2014-11-02 06:21:38

标签: c arrays pointers

为什么以下代码会生成正确的输出。理想情况下,我们应该通过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);
}

3 个答案:

答案 0 :(得分:1)

要回答实际问题,&#34;为什么会这样?&#34;,这是一个简短的答案。首先,您需要查看关联的问题,以了解int *pint 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);