c语言声明函数位置 c语言声明函数和定义函数( 四 )


?
12345
#include stdio.hmain(){ printf("hello,world\n");}
返回值类型为int的函数不用声明的规则改变了吗?规则没有改变 。改变了的是观念,人们已经不再倾向于代码的“至简”,而开始倾向于在代码中交代清楚每一个标识符的来龙去脉 。从C89开始倡导在函数调用之前一定要有函数声明,但并没有强求 , 而在C99这已经是强制性的要求了 。由于《The C Programming Language》第二版正值ANSI C标准颁布(1989)前夕出版,所以这种变化也应该视为ANSI C标准的倾向性以及KR对新标准的认同 。尽管这个例子没有完全反映出来这种认同 。
为什么说没有完全反映出来这种认同呢?因为这个main()的定义并没有按照函数原型(Function prototype)的方式来写 , C90中规定不带参数的main()函数应该这样写:
?
1
int main(void) { /*. . .*/}
但同时规定那个int可以省略 。C90把()内不写任何内容视为过时的写法,尽管C90无奈地容忍了它(The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.) 。
为什么要容忍?因为有许多老式的代码还在用 。
如果以C99的标准看这个main()写得如何呢?C99不容许省略int 。但同样只把()内不写任何内容视为过时,而没有完全禁止,可见习惯力量的顽固 。
那又为什么说KR对新标准的认同呢?《The C Programming Language》第二版中的其他函数定义和函数类型声明基本上都改成了函数原型风格 。比如,在讲解main()函数的参数时,KR把原来的main()函数
?
1234567
#include stdio.hmain(argc,argv)int argc;char *argv[];{ /*…… */ return 0;}
改成了:
?
123456
#include stdio.hmain(int argc, char *argv[]){ /*…… */ return 0;}
前一个写法今天已经差不多绝迹,后一个main()以今天的眼光来看有些奇怪,main()的参数是用函数原型风格写的,但却没有写main()返回值的类型,给人有点半新半旧的感觉 。尽管不能说它违背C90(因为C90容许不写main()前面的int),但如果写上了返回值的类型int,就同时满足现代C99标准的要求了 。
这里出现的“return 0;”是怎么回事?这在现代C语言中已经是司空见惯了,它返回给操作系统一个值以表明程序是在何种状态下结束的 。但在另一段代码中,KR似乎又走得太远:
?
1234567
#include stdio.hmain(int argc,char *argv[]){ int found = 0 ; /*……计算found的值 */ return found;}
这个实在有些“标新立异”,居然把计算结果返回给了操作系统,颇有突破常规之嫌 。
那前面几个没有“return 0;”的main()函数会怎么样?按照C90标准,会返回一个不确定的int类型的值,如果确实不关心这个返回值是多少,不写确实可以 。但C99却要求编译器在编译的时候帮忙给补上这个“return 0;”,C99在必须写int这个问题上没有迁就懒人 , 但在这里却对偷懒的做法给予了迁就 。问:如果确实不关心main()函数的返回值,把main()的返回值定义为void类型如何?我看到许多书上都这样写的 。
?
12345
#include stdio.hvoid main(){ printf("This is a C program.\n");}
这在C99之前是一种野路子写法,究竟从哪里冒出来的,无据可考 。但前几年的主流教科书中这种写法很常见 。KR(C语言的发明者)没有这样写过,C90国际标准也不承认这种写法 。Bjarne Stroustrup(C++语言的创始人)在他的关于C++的FAQ中,在回答是否可以写“void main()”时愤怒地回答说这种写法在C++和C中都不曾有过 。事实上 , 很多C语言专家都认为“void main()”非常邪恶 。
因此,在C99之前 , 这是不符合标准的写法 。尽管这段代码的功能似乎是输出“This is a C program.”,但其实却不是一个“C program” 。

推荐阅读