主要原因是main函数为什么不能被声明为const

5

我通常看到 main() 函数被称为:

  • int main(int argc, char** argv)
  • int main(int argc, char* argv[])
  • int main(void)

关于这些定义:

  1. 严格地说,对于 char** argvchar* argv[],哪一个更好还是它们100%可互换的吗?
  2. 由于 argc 和参数字符串(应该是?)都是不可变的,为什么它们都不是const类型的?或者这只是出于惯例/历史目的而省略了。我想这可以通过以下方式完成:const char **argv = (const char **) argv;,但很奇怪为什么没有这样做(例如,是否有更改接收到的参数的原因?)

这个回答解决了你的问题吗?为什么argc不是一个常量? - Sprite
  1. 它们100%完全相同
  2. argv参数不是不可变的...虽然我会对“扩展”它们感到不满..argv[1][len = strlen(argv[1])] = '*'; argv[1][len+1] = 0;
- pmg
1
@Sprite 嗯,那很好,但问题是一个被标记为 C,另一个被标记为 C++ -- 也许可以将重复的标记为 C 和 C++ 两者? - David542
4
一般来说,在涉及到argc的情况下,没有太多理由将值参数声明为const。这样做也会使漂亮的习惯用法while(argc--) printf("%s\n", *argv++);无效化。 - dxiv
1
请参阅argv[n]是否可写?” - chux - Reinstate Monica
显示剩余3条评论
3个回答

6
由于它们都是可修改的:
N1570 §5.1.2.2.1/2:

参数 argc 和 argv 以及由 argv 数组指向的字符串应可被程序修改,并在程序启动和终止之间保留其最后存储的值。


好的,一个程序想要修改它们的原因可能是什么? - David542
4
为什么不呢?例如:当数字被传递时,你想要将逗号替换为句点,转换为小写/大写,移除/替换一个扩展名……有许多原因可以修改一个字符串。 - David Ranieri
1
我最近刚好利用了这个。我想从外部源复制/粘贴一个数字字符串并删除其中的逗号,直接在原地操作比创建另一个字符串更容易实现。 - Weather Vane
@DavidRanieri 谢谢。您能分享一下包含您上面列出内容的C标准文件/HTML文档的链接吗? - David542
当然:https://port70.net/~nsz/c/c11/n1570.html - David Ranieri
请注意,根据此引用,argcargvargv[][]是可修改的。argv[]是不清楚的部分。 - chux - Reinstate Monica

2
  1. 它们是完全可以互换的。
  2. 修改它们是有效的,有时在程序中存在一条命令行处理器链,每个处理器都会在将其传递给链中下一个处理器之前删除与其相关的选项。在这种情况下,argc通过指针传递给处理器。你可以在QT库中看到一个例子,不是用C而是用C++: QApplication构造函数.

1

这里对*argv[]**argv之间的区别(或非区别)进行了长时间的讨论:

我应该使用char ** argv还是char * argv[]?

两者都被广泛使用,在这种特定情况下它们之间没有实际区别。

至于指针是否应该是const,这是一个有趣但相当学术的争论。在C中,我非常相信const正确性,但是main()是我认为它具有反生产力的地方之一。习惯上写char **argv,无论这些指针是否真正是const,或者您的代码是否将它们视为常量。在Linux上,它们实际上不是常量--程序可以修改它们,尽管很少需要。

我的感觉是,如果你不写 char **argvchar *argv[] 以外的任何东西,只会导致混淆。我最近看到了一些例子,其中 main() 被定义为接受 char *argv[argc+1]。这在现代 C 编译器中是允许的,但 C 程序员并不习惯看到这种形式的写法。

3
argv 中的指针以及它们所指向的字符串并不是 const 类型,这是毋庸置疑的。可以在 David 的回答 中看到 C 语言标准中的引用。此外,char *argv[argc] 是错误的。由于 C 语言标准要求在 argv 数组末尾有一个 NULL 指针,因此数组的实际大小是 argc+1 - user3386109
2
这是一个有趣但相当学术的辩论。这根本不是学术讨论。根据C标准,程序应该可以修改argcargv中指针值以及这些指针所引用的字符串。 - Andrew Henle
1
这是学术性的,因为指示某些东西是否在技术上可修改并不是const-correctness的重点。如果我将一个函数定义为void foo(const char *bar),我并不是因为平台中的某些东西禁止它或者调用者实际上是常量而防止函数修改bar。我使用const来表明我的函数实际上不会通过其指针修改bar--如果我编写代码这样做将是一个错误。如果我声明argvconst指针组成,编译器不会抱怨,有些人建议这样做。 - Kevin Boone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接