我无法计算我在那里和这里看到 C 代码的次数,将main定义为
int main() { ...
当我编译它时
gcc -ansi -pedantic -Wstrict-prototypes -Werror foo.c
它出错了
foo.c:2: warning: function declaration isn't a prototype
为什么会这样
int main(void)
需要使错误消失吗?
因为定义
int main() { /* ... */ }
不包括原型;它没有指定参数的数量或类型。
这:
int main(void) { /* ... */ }
确实包括一个原型。
使用空括号,您是说它main
采用固定但未指定数量和类型的参数。使用(void)
,您明确表示它不需要任何参数。
对于前者,调用如下:
main(42);
不一定会被诊断出来。
这可以追溯到原型被引入语言之前的 ANSI 之前的日子,大多数函数都是用空括号定义的。那时,这样写是完全合法的:
int foo();
int foo(n)
int n;
{
/* ... */
}
...
foo(42);
当原型被添加到语言中时(从 C++ 中借用),有必要保留空括号的旧含义;添加了“新”(这是 1989 年)语法(void)
,因此您可以明确地说函数不带参数。
(C++ 有不同的规则;它不允许老式的非原型函数,空括号意味着函数不带参数。C++ 允许(void)
与 C 兼容的语法,但通常不推荐。)
最佳实践是使用(void)
,因为它更明确。表单是否有效还不完全清楚int main()
,但我从未见过不接受它的编译器。
它不会出错 - 它会发出警告。该标志说明了一切:它希望您关心main
(通常是int argc, char **argv)
.
根据gcc 文档,添加时会发出警告,-Wstrict-prototypes
因为:
-Wstrict-prototypes(仅限 C 和 Objective-C)
如果在声明或定义函数时未指定参数类型,则发出警告。(如果前面有一个指定参数类型的声明,则允许在没有警告的情况下进行旧式函数定义。)
但对你来说这是一个错误,因为-Werror
:
-Werror
将所有警告变成错误。
一般来说,定义一个main()
类似的东西是错误的(不管你在这里看到了什么),C 规范定义了main()
5.1.2.2.1 中的外观:
程序启动时调用的函数名为 main。实现没有声明这个函数的原型。它应定义为返回类型为 int 且不带参数:
int main(void) { /* ... */ }
或者带有两个参数(这里称为 argc 和 argv,尽管可以使用任何名称,因为它们是声明它们的函数的局部变量):
int main(int argc, char *argv[]) { /* ... */ }