为什么argc不是常数?

Din*_*han 102 c++ program-entry-point const effective-c++ argc

int main( const int argc , const char[] const argv)
Run Code Online (Sandbox Code Playgroud)

正如有效的C++第3项规定"尽可能使用const",我开始思考"为什么不制作这些'常数'参数const"?

是否存在argc在程序中修改值的任何情况?

Joe*_*e Z 113

在这种情况下,历史是一个因素.C将这些输入定义为"非常数",并且与(很大一部分)现有C代码的兼容性是C++的早期目标.

某些UNIX API,例如getopt,实际上会进行操作argv[],因此也不能const出于这个原因.

(旁白:有趣的是,虽然getopt原型表明它不会修改argv[]但可能会修改指向的字符串,但Linux手册页表明它会getopt置换其参数,看起来他们知道它们是顽皮的.公开的手册页集团没有提到这种排列.)

constargcargv不会买太多,它会导致一些老派的编程习惯,如:

// print out all the arguments:
while (--argc)
    std::cout << *++argv << std::endl;
Run Code Online (Sandbox Code Playgroud)

我用C编写了这样的程序,我知道我并不孤单.我从某处复制了这个例子.

  • 对不起,[我看过的文档](http://man7.org/linux/man-pages/man3/getopt.3.html) 不一致:签名不允许这样的排列。参见 [示例](http://coliru.stacked-crooked.com/a/6fcab492c134b11c)。但是,下面的文字说它确实置换了。所以,我正在删除downvote。 (2认同)

Jon*_*ler 36

C标准(ISO/IEC 9899:2011)说:

5.1.2.2.1程序启动

1程序启动时调用的函数被命名main.该实现声明此函数没有原型.它应该使用int的返回类型定义,并且没有参数:

int main(void) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

或者有两个参数(这里称为argcargv,虽然可以使用任何名称,因为它们是声明它们的函数的本地名称):

int main(int argc, char *argv[]) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

或同等学历; 10)或以某种其他实现定义的方式.

2如果声明它们,main函数的参数应遵守以下约束:

  • argc应为非负值.
  • argv[argc] 应为空指针.
  • 如果值argc大于零,则argv[0]通过 argv[argc-1]包含的数组成员应包含指向字符串的指针,这些指针在程序启动之前由主机环境给出实现定义的值.目的是在程序启动之前从托管环境中的其他地方向程序提供信息.如果主机环境不能提供大写和小写字母的字符串,则实现应确保以小写形式接收字符串.
  • 如果值argc大于零,则指向的字符串argv[0] 表示程序名称; argv[0][0]如果程序名不能从主机环境获得,则应为空字符.如果值argc大于1,则argv[1]through 指向的字符串argv[argc-1] 表示程序参数.
  • 数组指向的参数argcargv字符串argv应由程序修改,并在程序启动和程序终止之间保留它们最后存储的值.

10)因此,int可以替换为定义为的typedef名称int,或者argv可以写为 的类型char **argv,依此类推.

请注意最后一个要点.它说,双方argcargv应修改.它们不必修改,但可以修改它们.


raz*_*zeh 23

argc通常不是常量,因为main()前置日期的函数签名const.

由于argc是一个堆栈变量,因此更改它不会影响除您自己的命令行处理之外的任何内容.

当然,const如果你愿意,你可以自由地宣布它.


Che*_*Alf 8

const形式参数的顶级不是函数类型的一部分.您可以根据需要添加或删除它:它只影响您可以使用函数实现中的参数执行的操作.

所以argc你可以随意添加一个const.

但是因为argv你不能在const不改变功能签名的情况下制作字符数据.这意味着它不是标准main功能签名之一,并且不必被识别为main功能.所以,不是一个好主意.


main在非玩具程序中不使用标准参数的一个很好的理由是,在Windows中,它们无法表示实际的程序参数,例如具有国际字符的文件名.这是因为在Windows中,它们是由非常强大的约定编码为Windows ANSI.在Windows中,您可以根据GetCommandLineAPI函数实现一些更可移植的参数访问工具.


综上,没有什么能够阻止您添加constargc,但最有用const的-ness argv会给你一个非标准的main功能,最有可能不承认.令人高兴的是(以具有讽刺意味的方式),有充分的理由不使用main便携式严重代码的标准参数.很简单,对于实践中他们只支持旧的ASCII,只有英文字母.