谁知道为什么这个编译成功了?

时间:2012-11-19 12:47:56

标签: c

有人知道为什么this在C中成功编译?

int main(){
     display();
   return 0;
 } 

 void display(){
     printf("Why am I compiling successfully?");
 }

我认为当没有提供声明时C假设extern int Function_name(arg1,arg2,...){}.因此这应该给出一个错误但是它有效!我知道Ideone正在压制警告,但我的问题是为什么它不是直接错误? (但在C ++中它是直接的错误)

5 个答案:

答案 0 :(得分:8)

调高编译器中的警告级别,您应该收到2次警告,

display未声明,int假设

display已重新宣布

修改

旧版本的C(前C99)并没有真正对返回类型或参数类型感到困扰。你可以说这是K& R遗产的一部分。例如,如果您没有显式指定参数类型,编译器将根本不检查它们。

C ++更严格,IMO是一件好事。我总是提供声明,并且在用C编码时总是指定参数列表。

答案 1 :(得分:5)

它正在编译,因为C使用许多默认值向后兼容。在K& R C中,您无法指定函数原型,因此编译器只会假设您在调用函数时知道自己在做什么。

后来(至少是ANSI C,但也许在C99中),C真的没有办法区分

void display(void);
void display();

所以也必须接受空声明。

这就是为什么你可以先调用display()而不先定义它。

printf()类似。如果忘记-lc,将会收到链接器错误,但从编译器的角度来看,代码“足够好”。

一旦启用编译器必须提供的所有警告,它就会改变,当您禁用K& C兼容性或启用严格的ANSI检查时,它将失败并显示错误。

这就是“C”在“How to Shoot Yourself In the Foot Using Any Programming Language”列表中经常被列为“你射到脚下”的原因。

答案 2 :(得分:3)

取决于您的Cx(C89,C90,C99,...)

对于函数返回值,在C99之前明确规定如果没有可见的函数声明,则转换器提供一个。这些隐式声明默认为返回类型int

来自C Standard的理由(6.2.5第506页)

  

在C90之前,没有功能原型。开发人员期望   能够互换签名和未签名的论点   相同整数类型的版本。必须施展论据,如果   函数定义中的参数类型具有不同的符号,   被视为与C的易于进行的类型检查系统和a   很少侵入性的。原型的引入并没有完全发挥作用   远离论证的可互换性问题。省略号   符号规定没有人知道1590省略号   提供没有信息的预期参数类型。同样,为   函数返回值,在C99之前明确指定了   如果没有看到功能声明,则翻译提供一个。   这些隐式声明默认为返回类型的int。如果   实际的函数碰巧返回类型unsigned int,这样的   默认声明可能返回了意外的结果。许多   开发人员对功能声明有一种随意的态度。该   我们其他人不得不忍受委员会的后果   想要打破他们写的所有源代码。该   函数返回值的可互换性现在是一个有争议的问题,   因为C99要求在...处显示函数声明   调用点(不再提供默认声明)

答案 3 :(得分:1)

它可能会(假设你写的这样的声明),但由于你没有传递参数,它只是工作正常。如果您声明int main()实际应该是int main(int argc, char *argv[]),那就相同。

因此,如果您尝试从main传递一些参数(与默认参数不同),那么可能会在display中使用它们会失败。

顺便说一句,对我而言,它会编译,但会产生警告:

$ gcc z.c
z.c:8:6: warning: conflicting types for ‘display’ [enabled by default]
z.c:4:5: note: previous implicit declaration of ‘display’ was here

答案 4 :(得分:0)

当我使用gcc编译时,我会收到关于display重新声明的警告,正如您所期望的那样。

你收到了警告吗?

它可能会“运行”,因为C不会破坏函数名称(如C ++)。因此链接器会查找符号'display'并找到一个符号。链接器使用此地址运行display。我希望结果不会像你期望的那样。