C中main()的不同约定

我唯一接触过编程的是Java,在那里我没有遇到(到现在为止)编写main方法的不同惯例。我一直在学习c(K&R和C编程现代方法)的来源,他们使用的方式非常不同forms的主要方法(function)。

K&R版本到现在为止:

main() { blah blah blah; } 

C编程现代方法

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

要么

 int main() { blah blah blah; //returns nothing } 

为了让事情更加混乱我见过人们这样做:

 int main(void) { blah blah blah; } 

虽然他们要么返回0,要么没有。 我没有在我没有受过教育的假设中认为这只是一个标准问题,但可能更具概念性或更深层次。 有人能解释一下这个问题吗?

  • K&R风格已经过时,根据C标准不再正确。

  • 有效的签名是

     int main(void) 

     int main(int argc, char *argv[]) 

    或者,等效,因为函数中的数组类型仍然调整为指针类型:

     int main(int argc, char **argv) 
  • 签名

     int main() 

    碰巧也是有效的,因为空参数列表意味着任何数量的参数,没有描述 *)。 AFAIK,这可能会有变化,所以不要这样写。 写void是你如何表达这个函数不用 C中的参数

  • C的实现可以自由地提供其他实现定义的入口点。 但我上面列出的两个是唯一由标准保证的。

  • C99为main()引入了一个特殊规则,声明如果函数没有返回任何内容,则隐式返回值0 。 因此, 只有在主要内容中 ,您才能跳过return 。 我的建议是:不要。 这只是令人困惑。 但这是一个意见。


*)注意这在C ++中是不同的 ,其中parantheses之间没有任何东西确实意味着:没有参数。

如果没有给出C的预标准化版本(称为K&R C)则具有默认类型int的概念。 所以在K&R这个:

 main() { 

是相同的:

 int main() { 

至于int main()int main(void)之间的区别,空参数列表表示该函数采用未指定数量的参数,而(void)作为参数列表表示该函数不采用任何参数。 前者是可以接受的,但后者是首选,因为它更明确。

关于return语句的使用,具有非void返回类型的函数必须使用return来返回一个值, 除了 (从C99标准开始) main函数。 在main的情况下,缺少return语句意味着返回值为0。

因为在C99中添加了main的隐式return 0 ,所以您将看到一些显式返回的代码,而某些代码不依赖于程序员所遵循的标准版本。

从最新的C语言标准开始, main有两个标准签名:

 int main( void ) // void indicates "takes no arguments" 

 int main( int argc, char *argv[] ) // or char **argv, it means the same thing in this context 

名称argcargv是任意的; 如果您愿意,可以使用不同的名称。

实现可以main提供额外的有效签名 – 检查编译器文档。

如果您的程序没有采用任何命令行参数,请使用第一个表单,否则使用第二个表单。

C函数声明和定义语法随着时间的推移有所发展,这就是不同引用使用不同约定的原因。

隐式打字

首先,C最初允许隐式int声明 – 如果编译器看到函数定义或没有类型说明符的声明,它假定函数返回int

 foo(); // modern equivalent: int foo( void ) 

直到1999年的标准才允许这样做,尽管在此之前我们大多数人都认为这种风格很糟糕。

void关键字直到1989年标准才被引入。 作为类型说明符,它表示没有值的类型。 作为函数参数列表中的标识符,它表示该函数不带参数。

在引入void关键字之前,没有好的方法(除了文档之外)区分返回您要使用的值的函数与刚刚执行某些操作的函数。 我们中的一些人使用“隐式int ”约定来表明这些函数并不意味着返回任何有意义的东西:

 foo(); /* returns int, but return value not meant to be used */ int bar(); /* returns int, return value meant to be used */ 

同样,这只是一个惯例,远非普遍。 现在我们使用void关键字:

 void foo(); /* does not return a value */ int bar(); /* returns int */ 

函数原型语法

最初,函数定义看起来像这样:

 foo( bar, bletch, blurga ) int bar; double bletch; char *blurga; { /* function body */ } 

参数列表仅指定参数的名称 ,而不是其类型; 这是在函数声明符和函数体的开头{之间的一组单独的声明中完成的。 不带参数的函数在函数定义中有一个空标识符列表:

 blah( ) { /* function body */ } 

函数声明只指定了函数的名称和返回类型; 它根本没有指定参数:

 foo( ); /* no bar, bletch, or blurga */ 

函数声明中的空标识符列表指示该函数采用未指定数量的参数,而不是零参数。 编译器可以检查函数调用的返回类型是否正确使用,但无法检查调用中参数的数量和类型是否正确。

1989语言标准引入了函数原型语法的概念,其中每个参数的类型及其名称在参数列表中指定:

 foo( int bar, double bletch, char *blurga ) { /* function body */ } 

这适用于函数声明和定义:

 foo( int bar, double bletch, char *blurga ); 

此更改允许编译器检查函数调用中参数的数量和类型是否正确,以及返回类型。 此外,可以在参数列表中使用void关键字来指示函数在定义声明中都没有参数:

 blah( void ); /* declaration, returns int, takes no parameters */ blah( void ) /* definition */ { /* function body */ } 

所以,是的,根据您正在使用哪种语言修订版, main将以不同的方式编写:

K&R:

 main() main( argc, argv ) { int argc; ... char *argv[]; } { ... } 

C89:

 main( void ) main( int argc, char *argv[] ) { { ... ... } } 

C99及以后:

 int main( void ) int main( int argc, char *argv[] ) { { ... ... } } 

C标准将main签名定义为

 int main(void) 

要么

 int main(int argc, char *argv[]) 

添加return 0; 作为main函数的最后一个语句是可选的。
标准还说了一些实现定义的原型。 int main()被GCC编译器接受。

main()是一个旧学校原型,几乎已弃用。