荒谬的编译

时间:2011-08-15 06:43:27

标签: c

这是一个基本的C代码,根据我应该抛出三个错误(函数没有定义,函数没有返回任何东西,函数参数丢失)。但令我惊讶的是它没有扔掉任何东西,它编译并给出了一些垃圾结果:

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char *argv[])
{
    int a=f1();
    printf("a %d\n",a);
    system("PAUSE");    
    return 0;
}


f1(int *t)
{
       printf("t %d", t);
}

PS:我在Windows上使用gcc编译器。

6 个答案:

答案 0 :(得分:4)

在C中,当未声明函数时,假定返回int并继续编译(btw this can lead to nasty bugs)。如果声明函数没有类型(因为f1()在您的代码中,则假定它返回int。不从非void函数返回值(如在代码中)是未定义的行为。

因此,您提到的所有要点都不会导致编译错误。不需要未定义的行为来阻止程序运行 - 程序可能会运行,甚至可能产生漂亮的结果。

答案 1 :(得分:2)

首先,您没有启用警告进行编译。您通常应该至少使用-Wall开关调用gcc - 对于您的示例代码,它会给出:

x.c: In function 'main':
x.c:7: warning: implicit declaration of function 'f1'
x.c: At top level:
x.c:15: warning: return type defaults to 'int'
x.c: In function 'f1':
x.c:16: warning: format '%d' expects type 'int', but argument 2 has type 'int *'
x.c:17: warning: control reaches end of non-void function

其次,它编译的原因是它中的所有错误都是一种称为“未定义行为”的形式,这意味着编译器不是 required 来诊断它们并停止编译 - 它可以简单地产生垃圾结果。

答案 2 :(得分:2)

如果您使用gcc的-Wall选项启用所有警告,您可能会更高兴。然后你会在编译时看到这个:

C:\test>make
gcc -Wall prog.c -o prog
prog.c: In function 'main':
prog.c:7:5: warning: implicit declaration of function 'f1'
prog.c: At top level:
prog.c:14:1: warning: return type defaults to 'int'
prog.c: In function 'f1':
prog.c:16:8: warning: format '%d' expects type 'int', but argument 2 has type 'int *'
prog.c:17:1: warning: control reaches end of non-void function

您还可以使用-Werror将所有警告转为错误(因此您不得不修复它们)。

答案 3 :(得分:1)

尝试使用-Wall标志再次进行编译。这会打开所有警告,然后你会看到很多:

c.c: In function ‘main’:
c.c:7: warning: implicit declaration of function ‘f1’
c.c: At top level:
c.c:15: warning: return type defaults to ‘int’
c.c: In function ‘f1’:
c.c:16: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘int *’
c.c:17: warning: control reaches end of non-void function

由于您没有任何编译时错误,只有警告,因此代码编译良好。它只是不会很好地执行。

答案 4 :(得分:1)

f1被认为具有隐式原型'int f1(int)'。 因此呼叫有效。 f1不返回任何内容,而隐式支持返回int:行为未定义。 编译器可能会警告您隐式原型与定义不一致。它也可以要求适当的回报。这是编译器内部静态分析可以执行的检查的一部分:gcc不执行此操作,其他人可能执行此操作。 无论如何,编译器通常不保证任何有关非ISO符合性程序的内容。

答案 5 :(得分:0)

如果您在gcc命令中添加-Wall,则会收到一些警告。我猜它有效,因为旧式C具有松散的功能原型。并假设未知函数返回int。链接器工作,因为没有未定义的符号(f1存在),但你得到垃圾,因为堆栈上传递的内容(即什么都没有)不是预期的。