开发者

Absurd compilation

This is a basic C code, which according to me should have thrown three errors (function not defined, function not returning anything, function argument missing). But to my surprise it threw nothing, it compiled and gave some garbage results:

#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: I am using a gcc compiler on windows.


In C when a function is not declared is is assumed to return int and compilation continues (btw this can lead to nasty bugs). If the function is declared without a type (as f1() is in your code it is assumed to return int. Not returning a value from a non-void function (as in your code) is undefined behavior.

So none of the points you mention are required to cause a compilation error. Undefined behavior is not required to prevent your program from running - the program might run and might even produce good looking results.


Firstly, you were not compiling with warnings enabled. You should usually invoke gcc with at least the -Wall switch - for your example code, that gives:

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

Secondly, the reason that it compiles is that all of the errors in it are of a form called "undefined behaviour", which means that the compiler isn't required to diagnose them and stop compilation - it can simply produce garbage results.


You would probably be happier if you used gcc's -Wall option to enable all warnings. Then you would see this while compiling:

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

You can also use -Werror to turn all warnings in to errors (so you are forced to fix them).


Try compiling again with the -Wall flag. That turns on all warnings, then you'll see plenty:

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

Since you don't have any compile time errors, just warnings, the code compiles fine. It just won't execute very well.


f1 is considered to have the implicit prototype 'int f1(int)'. Hence the call is valid. f1 does not return anything whereas it is implicitly suppoed to return an int: the behaviour is undefined. The compiler could warn you that the implicit prototype does not agree with the definition. It could also ask for a proper return. This is part of the checks that the static analysis inside the compiler could perform: gcc does not do it, others may. In any case compilers usually do not guarantee anything about non ISO conforming programs.


If you add -Wall to your gcc commands you should get some warnings. I guess it works as old style C had loose function prototyping. And will assume unknown functions return int. The linker worked because there were no undefined symbols (f1 exists) but you got garbage as what was passed on the stack (i.e. nothing) was not what was expected.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜