我们可以将CV限定符添加到main的参数中吗?

时间:2016-07-05 04:35:48

标签: c++ c gcc clang language-lawyer

据我所知,在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){}

Live on Coliru

上面的代码是否合法?换句话说,我们可以将CV限定符添加到main的参数中,还是只是编译器的扩展而不需要诊断?

2 个答案:

答案 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[]) { /* ... */ }

     

或同等的;或者以其他一些实现定义的方式。

添加了constvolatile限定符的定义与所显示的表单不同,因此实现没有义务接受它。但由于该部分不是约束,因此也不需要实现投诉。特别是,如果某个实现文档表明它接受const和/或volatile限定符,则它们对于该实现完全有效

(实际上,大多数编译器可能不会抱怨。)

请注意,这仅适用于托管实施。对于独立实现(通常用于没有操作系统的嵌入式目标):

  

...在程序中调用的函数的名称和类型   启动是实现定义的。

(5.1.2.1第1段),这意味着对于独立实现的主要功能有 no 可移植定义(甚至不需要称为main)。