据我所知,在C或C ++中,main
的签名应为int main(void)
(void
在C ++中是可选的)或int main(int, char**)
。但是,以下代码在gcc / g ++ / clang / clang ++中编译时没有警告(-Wall -Wextra -Wpedantic
)
int main(int, const char * const * const argv){}
上面的代码是否合法?换句话说,我们可以将CV限定符添加到main
的参数中,还是只是编译器的扩展而不需要诊断?
答案 0 :(得分:4)
C++11
标准允许实现接受它喜欢的任何签名,它只强制要求提供两个。它还必须具有int
的返回类型。
3.6.1主要功能 [basic.start.main]
2 实现不得预定义主函数。此功能不应过载。它应该具有int类型的返回类型,否则其类型是实现定义的。所有实施都应该 允许以下两个主要定义:
int main() { /* ... */ }
和
int main(int argc, char* argv[]) { /* ... */ }
所以要解决主要问题:
我们可以将CV限定符添加到main的参数吗?
我们可以如果实现支持它但是如果我们这样做,则代码不太可能是可移植的。
如果代码将(最多) cv限定符添加到参数变量本身,而不是其指向的类型,则代码将只是完全可移植的:
// still portable, same signature as int main(int, char**)
int main(int, char** const argv);
// not portable
int main(int, char* const* argv);
// not portable
int main(int, const char** argv);
答案 1 :(得分:3)
请记住,C和C ++是两种不同的语言。两者的答案恰好相同,但值得涵盖C standard所说的内容 - 特别是考虑到语言 - 律师标签。链接是N1170的C11草案。
第5.1.2.2.1节涵盖托管实现的main
定义:
程序启动时调用的函数名为
main
。该 实现声明此函数没有原型。应该是 使用返回类型int
定义且没有参数:<强>
int main(void) { /* ... */ }
强>或有两个参数(此处称为
argc
和argv
, 虽然可以使用任何名称,因为它们是函数的本地名称 他们被宣布):<强>
int main(int argc, char *argv[]) { /* ... */ }
强>或同等的;或者以其他一些实现定义的方式。
添加了const
或volatile
限定符的定义与所显示的表单不同,因此实现没有义务接受它。但由于该部分不是约束,因此也不需要实现投诉。特别是,如果某个实现文档表明它接受const
和/或volatile
限定符,则它们对于该实现完全有效。
(实际上,大多数编译器可能不会抱怨。)
请注意,这仅适用于托管实施。对于独立实现(通常用于没有操作系统的嵌入式目标):
...在程序中调用的函数的名称和类型 启动是实现定义的。
(5.1.2.1第1段),这意味着对于独立实现的主要功能有 no 可移植定义(甚至不需要称为main
)。