【问题标题】:Reason main-C isn't const原因 main-C 不是 const
【发布时间】:2021-01-07 22:44:11
【问题描述】:

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

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

与这些定义相关:

  1. 从技术上讲,char** argv 和 char* argv[] 是一个优先于另一个,或者这 100% 可以互换?
  2. 因为argc 和参数字符串(应该是?)都是不可变的,为什么它们不是const?还是这无关紧要,只是出于惯例/历史目的而被省略?我想这可以通过:const char **argv = (const char **) argv; 来完成,但很好奇为什么这还没有完成(例如,是否有理由更改收到的参数?)

【问题讨论】:

  • 这能回答你的问题吗? Why is argc not a constant?
  • 1) 它们是 100% 绝对相同的 2) argv 参数不是一成不变的……不过我不赞成“扩展”它们……argv[1][len = strlen(argv[1])] = '*'; argv[1][len+1] = 0;
  • @Sprite 是的,这很好,但问题是一个被标记为 C 而另一个被标记为 C++ - 可能有 C 和 C++ 标记的副本?
  • 关于argc 通常没有太多理由将值参数声明为const。这也会使非常惯用的while(argc--) printf("%s\n", *argv++); 无效。

标签: c pointers constants main


【解决方案1】:

因为它们都是可修改的:

N1570 §5.1.2.2.1/2:

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

【讨论】:

  • 好的,程序想要修改它们的原因可能是什么?
  • 为什么不呢?一个例子:你想在传递数字时用点替换逗号,转换为小写/大写,删除/替换扩展名......修改字符串的原因有很多
  • 我最近利用了这一点。我想从我从外部源复制/粘贴的数字字符串中删除逗号,并且很容易就地执行此操作,而不是创建另一个字符串。
  • @DavidRanieri 谢谢。您能否分享一个指向包含您上面列出的内容的 C 标准文件/html 文档的链接?
【解决方案2】:
  1. 它们完全可以互换。
  2. 修改它们是有效的,有时程序中有一个命令行处理器链,每个都删除与其相关的选项,然后将其传递给链的下一个处理器。在这种情况下,argc 通过指针传递给处理器。您可以在 QT 库中看到一个示例,不是 C 语言,而是 C++ 语言:QApplication constructor。

【讨论】:

    【解决方案3】:

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

    Should I use char** argv or char* argv[]?

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

    至于指针是否应该是const 不是——这是一个有趣的,而是学术辩论。我非常相信 C 中的 const 正确性,但 main() 是我认为适得其反的地方。无论这些指针是否真的是const,或者您的代码是否将它们视为常量,写char **argv 都是惯用的。在 Linux 上,它们实际上不是恒定的——程序可以修改它们,尽管很少需要。

    我的感觉是,如果你写的不是char **argv 或char *argv[],只会引起混乱。我最近看到了将main() 定义为采用char *argv[argc+1] 的示例。现代 C 编译器允许这样做,但 C 程序员不习惯看到这种情况。

    【讨论】:

    • argv 中的指针和它们指向的字符串不是const,句号。没有辩论。请参阅 David's answer 中 C 标准的引用。另外,char *argv[argc] 是错误的。数组的实际大小是 argc+1,因为 C 标准要求在 argv 数组的末尾有一个 NULL 指针。
    • 这是一场有趣的学术辩论根本不是学术讨论。根据 C 标准,argc 和 argv 中的指针值以及这些指针所引用的字符串都应由程序修改。
    • 这是学术性的,因为指出某事物在技术上是否可修改并不是 const-correctness 的意义所在。如果我将一个函数定义为void foo (const char *bar),我不会阻止该函数修改bar,因为平台中的某些东西不允许它,或者因为它在调用者中实际上是常量。我使用const 表示我的函数实际上并没有通过它的指针修改bar——如果我编写代码来这样做,那将是一个错误。如果我声明 argv 包含 const 指针,编译器不会抱怨,有些人建议这样做。
    猜你喜欢
    • 2011-07-26
    • 1970-01-01
    • 2018-08-31
    • 2011-02-04
    • 1970-01-01
    • 2017-03-13
    • 1970-01-01
    • 2011-09-24
    • 2017-04-10
    相关资源
    最近更新 更多