C标准为main
指定了两种定义形式
托管实现:
int main(void) { /* ... */ }
和
int main(int argc, char *argv[]) { /* ... */ }
可以按照与上述“等同”的方式定义
例如,您可以更改参数名称,用typedef替换
int
名称定义为int
,或将char *argv[]
写为char **argv
)。也可以“以某些其他实现定义的方式”定义它
-这意味着如果
int main(int argc, char *argv[],char *envp)
之类的东西在实现文档中说明是有效的。“以其他实现定义的方式”子句不在
1989/1990标准;它是按1999年标准添加的(但
较早的标准允许扩展,因此可以实现
仍然允许其他形式)。
我的问题是:鉴于目前的(2011)ISO C标准,
表格的定义
int main() { /* ... */ }
对于所有托管实现均有效且可移植?
(请注意,我不是在解决
void main
或使用在C++中不带括号的
int main()
。这只是关于ISO C中的
int main(void)
和int main()
之间的区别。) 最佳答案
没有。
根据标准的规范措辞,定义
使用不带void
关键字的空括号不是其中一种
必须接受的表格,严格来说是
这样的程序是不确定的。
引用:
N1570
5.1.2.2.1节。 (已发布的2011 ISO C标准
免费提供,其措辞与N1570草案相同。)
第1段说:
在约束之外使用“应”一词意味着任何
违反它的程序具有未定义的行为。因此,例如,如果我写:
double main(unsigned long ocelots) { return ocelots / 3.14159; }
不需要合格的编译器来打印诊断,但是它是
也不需要编译程序,或者如果编译的话
使其具有任何特定方式的行为。
如果
int main()
与int main(void)
等效,则它对于任何符合标准的托管实现都是有效且可移植的。
但这并不等同。
int main(void) { }
提供声明(在本例中为原型(prototype))和
定义。该声明通过使用
void
关键字指定该函数没有参数。该定义指定相同的内容。如果我改写:
int main() { }
然后我使用的是旧式的声明和定义。 (这样
声明和定义已过时,但它们仍然
语言定义的一部分,所有符合标准的编译器必须
仍然支持他们。)
作为声明,它不指定参数的数量或类型
该功能所期望的。作为定义,它没有定义任何参数,
但是编译器不需要使用该信息来诊断错误的调用。
DR #317包括C标准委员会2006年的一项裁决,即
()
的定义不提供与(void)
相同的原型(prototype)(感谢hvd查找该引用)。C允许递归调用
main
。假设我写:int main(void) {
if (0) {
main(42);
}
}
可见的
int main(void)
原型(prototype)指定main
采用没有争论。试图传递一个或多个参数的调用
违反约束,需要编译时诊断。
或者假设我写:
int main() {
if (0) {
main(42);
}
}
如果执行了
main(42)
调用,它将具有未定义的行为-但它没有违反约束,并且不需要诊断。
由于它受到
if (0)
的保护,因此调用永远不会发生,并且未定义的行为永远不会真正发生。如果我们假设
int main()
有效,那么任何人都必须接受此程序符合要求的编译器。但是正因为如此,它证明了
int main()
不等于int main(void)
,因此不包含在5.1.2.2.1中。
结论:按照标准的措辞,
允许执行以证明
int main() { }
是允许的。如果没有记录,仍然可以接受
它没有抱怨。但是合规的编译器也可能会拒绝
int main() { }
,因为它不是以下格式允许的形式之一该标准,因此其行为是不确定的。
但是仍然有一个开放的问题:作者的意图是
标准?
在1989年ANSI C标准发布之前,
void
关键字不存在。 ANSI前(K&R)C程序将定义main
要么作为main()
或作为
int main()
ANSI标准的主要目标是添加新功能(包括
原型(prototype))而不会破坏现有的pre-ANSI代码。说明
int main()
不再有效,将违反该目标。我怀疑C标准的作者无意
使
int main()
无效。但是书面标准并没有反射(reflect)该意图;它至少允许符合标准的C编译器
拒绝
int main()
。实际上,您几乎可以肯定会摆脱它。
我尝试过的每个C编译器都会接受
int main() { return 0; }
无投诉,行为等同于
int main(void) { return 0; }
但是出于多种原因:
()
以外的其他函数实际调用的其他函数,(void)
和main
之间的区别很重要)。 我建议始终编写
int main(void)
而不是int main()
。它可以更清楚地说明意图,您可以100%确保
编译器将接受它,而不是99.9%。
关于c - int main(){}(不带 “void”)在ISO C中是否有效且可移植?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29190986/