【问题标题】:Is it safe to rename argc and argv in main function?在主函数中重命名 argc 和 argv 是否安全?
【发布时间】:2016-08-25 00:58:43
【问题描述】:

许多程序对一些参数和字符串数组使用标准名称。主函数原型如下:int main(int argc, char *argv[]);。但是,如果我为这些变量选择自定义名称,我会破坏一些东西吗?

例如int main(int n_of_args, char *args[]);

在编译器的上下文中,一切都很好。这些变量对于 main 函数是局部的,因此它们可以有任何名称。简单的代码可以完美地构建和运行。但是这些名称可能会被预处理器使用。那么重命名这些参数是否安全?

PS 就我个人而言,我觉得这些名字很糟糕,因为它们看起来非常相似,而且只有一个字母不同。但是每个人都出于某种原因使用它们。

【问题讨论】:

  • 是的,完全安全。
  • 正如所有答案所说,是的,它是安全的。但请不要那样做。每个人都知道argcargv 是什么。 n_of_argsargs 对于不懂 C 或 C++ 的人来说可能更清楚——但那不是你的听众。
  • 可以这样做,这样做的理由还不够。每个人都知道这些是什么,并且他们确实希望它们是那样的。
  • 如果问题恰好是“如果我选择自定义名称,我会破坏某些东西吗”,而不是精确的答案是“是的,你会破坏良好的传统”;)
  • 翻转它们! .. 从一开始你就为工作保障奠定了基础:)

标签: c++ c main


【解决方案1】:

是的。它很安全,看起来很奇怪,但它不会破坏任何东西。

【讨论】:

    【解决方案2】:

    当然,您可以根据需要安全地重命名这些参数

    int main(int wrzlbrnft, char* _42[]) {
    }
    

    名字是写在沙子里的。它们对最终编译的代码没有任何影响。


    唯一重要的是,声明和定义的参数类型实际上匹配。

    main() 函数的签名本质上声明为

    int main(int, char*[]);
    

    如果您实际上需要在实现中使用它们,则需要命名它们。如前所述,使用哪些名称实际上无关紧要。

    【讨论】:

    • 只有一些标识符是“写在沙子里”的。函数名当然不是。
    • @SteveCox “函数名肯定不是。” 最后他们是。只是沙粒的数量:-P ...
    • 好的,但是认真的。编译后,目标代码中仍然有函数名。否则链接将不起作用
    • @πάνταῥεῖ:除非您特别努力删除它们,否则函数名称确实会保留在最终的可执行文件中。
    • @Kundor:在Windows上链接后,所有非特殊函数不保留名称
    【解决方案3】:

    是的,您可以根据需要重命名它们。它们只是函数参数名称,仅此而已。

    【讨论】:

      【解决方案4】:

      是的,它是安全的,只要您使用有效的变量名。它们是局部变量,因此它们的作用域不会超出 main 函数。

      来自C standard 的第 5.1.2.2.1 节:

      程序启动时调用的函数名为main。这 实现没有声明这个函数的原型。它应 用int 的返回类型定义并且不带参数:

      int main(void) { /*  ... */ }
      

      或带有两个参数(此处称为argcargv尽管任何 可以使用名称,因为它们对于它们所在的函数是本地的 声明):

      int main(int argc, char *argv[]) { /* ...   */ }
      

      或等价物;或以其他一些实现定义的方式

      话虽如此,使用 argcargv 以外的任何内容可能会使其他阅读您的代码的人感到困惑,这些人习惯于这些参数的常规名称。所以最好在清晰度方面犯错。

      【讨论】:

        【解决方案5】:

        是的,使用不同的名称是安全的。

        我个人并不推荐它,因为传统的argcargv 对于所有可能使用您的代码的其他C 程序员来说是如此广为人知和熟悉。从长远来看,使用你自己的、特殊的、不同的名字会给你的读者带来更多的困惑和/或挫败感,而不是因为你更喜欢你的名字而拯救你。

        “在罗马,做罗马人做的事。”

        【讨论】:

        • 然而,很少有非常明显的场景需要使用不同的名称,一个臭名昭著的场景是初始化 GLUT,glutInit(&argc, argv),其中必须以不同方式声明和初始化参数,以免让 GLUT 吃掉up 命令行参数,除非我们想要这样。 SO link
        • @user3078414 有趣的例子,但我不明白它如何说明必须命名的变量。根据其他问题中的示例,我们可以轻松编写int dummyargc = 1; char *dummyargv[1] = {(char*)"Something"}; glutInit(&dummyargc, dummyargv);
        • 谢谢@steve-summit。一些 API 文档恰好有误导性,因此这个线程对于突出 argc argv 命名约定最有帮助,就像您提供的答案一样。我只是把我的评论作为最好使用不同名称的例子。这是SO link
        【解决方案6】:

        名称 argcargv 实际上是 C++11 之前的 C++ 标准规定的。它说:

        所有实现都应允许以下两种 main 定义:

        int main ()
        

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

        然后继续讨论argcargv 的要求。

        所以从技术上讲,任何使用不同名称的程序都不符合标准,编译器可以拒绝它。当然,实际上没有编译器这样做。请参阅this thread on comp.std.c++,或this C++03 draft standard 的第 3.6.1 节。

        这几乎可以肯定只是一个疏忽,并且在 C++11 中进行了更改,而是说

        所有实现都应允许两者

        • () 的函数返回int
        • int,指向指向char的指针的指针)的函数返回int

        作为main (8.3.5) 的类型。在后一种形式中,为了 说明,第一个函数参数称为argc,第二个函数参数称为argc 函数参数被称为argv,…

        【讨论】:

          【解决方案7】:

          就编译器而言是安全的。

          这可能导致的唯一问题是混乱。阅读您的代码的人会期望这两个变量具有其标准名称。你甚至可以这样做:

          int main(int foo, char ** bar)
          {
              int argc;
              float argv;
          

          但我认为我不需要说明这种做法会有多糟糕。

          【讨论】:

            【解决方案8】:

            根据 C 标准,是的,您可以重命名,不会有任何影响。据我了解,在 C 语言中,默认的关键字/类型/令牌名称是根据用途/用途定义的,因此以同样的方式定义名称

            argc --> argument count
            
            argv --> argument vector
            

            这在使用方面也很有意义,所以你可以更改为任何名称,除了 Reserved names

            在GCC中,程序执行以函数名main开始,它不依赖于他的参数。

            当您为微控制器编写独立程序时,您无需担心名称main,而是可以定义自己的name 并更改Assembly entry_point 以指向您的函数。这取决于控制器编译器和预定义控制器源代码的可用性。我已经在 Code-warrior 下的飞思卡尔控制器中做到了这一点。

            我的笔记:

            最好遵循通用的标准/代码风格,让代码更可见、更易读

            【讨论】:

              【解决方案9】:

              如果你不喜欢变量名,为什么不用宏 #define 代替它们:

              #define yourCounterName argc
              #define yourVectorName  argv 
              

              您不会冒任何风险并产生“干净的解决方案”。

              【讨论】:

              • 那些不是常量,只是替换。
              【解决方案10】:

              我觉得每个人都很好地涵盖了技术 c++ 规则:答案是肯定的。让我们抛开传统以及这一特殊功能的特殊性和标志性这一事实,其中包含在此基础上不会更改的有效点。

              很多时候,我觉得选择的哲学很少被讨论,因此想就这个问题提供一个观点,因为我觉得这对于为什么要开始提出这个问题很重要。

              对我来说,这个问题涉及在一般代码中表达英语的选择。您似乎对简写描述感到困扰,特别是如果简写的文字看起来相似。但是,在您的示例中,将 argn 更改为 n_of_args 仅完成将一种简写形式更改为另一种形式的简写形式,而没有真正的附加值:澄清或其他可见属性。

              “数字”一词已被字母“n”替换。

              如果您是通过反简写的哲学来更改简写名称,那么这样的内容可能看起来更合适:

              main(int argumentCount, char ** argumentVector)

              我总是考虑两件事:根据事物的本质和/或隐含的用法来命名事物。称它为argumentVector 对我来说是多余的,因为作为向量的属性是由双重间接**暗示的。因此,我将如何编写代码的更好的长手是:** 参数。

              有些人会说名为argumentCount 的变量被声明为int 并且Count 不能为负,但你可以有一个负的int {无符号更好}。

              同样,它是什么以及如何使用在这种解释中发挥作用。如果它是一个计数,那么我会假设它永远不会是负数。毕竟,你怎么会有-2个苹果的计数。我会说,你欠两个苹果。如果它是一个数字,那么我预计可能会出现负面情况。这就是为什么额外的单词“of”对你很重要。那个,也许是集合所指的数字意味着一个特定的项目,而不是集合本身的一个属性。即:argumentsNumber = 5 意味着一个特定的参数,但不是 numberOfArguments。

              main(int maxArgumentsIndex, char ** arguments).

              这消除了歧义。将其称为索引消除了否定案例的歧义,还描述了它是什么,以及如何使用它。它还通过英文措辞暗示 max 是一个绝对值,并且在编写修改该值的代码时会感觉很奇怪(它应该是 const)。 'arguments' 在这里很有意义,因为它是复数形式,描述了它是什么,以及它应该如何使用。即使以这种方式解释也可能很危险,因为索引是 Count/NumberOf 的 -1。 5 个参数产生的 maxIndex 为 4!!

              任何其他功能,我会完全使用:

              void 函数( const unsigned int maxArgumentsIndex, const char ** 论据)

              并非所有情况都值得长手描述。事实上,有时简写会产生更多的可读性,特别是在编写诸如 Vec3f、矩阵、四元数等数学类的情况下......我几乎总是会尝试匹配数学语言而不是语言语言.浮动 x, y, z vrs。 float xComponent 等。

              我知道所有这一切都是一种风格选择,但从长远来看,意识到这些选择确实会有所帮助。我保证当数组不是以复数形式编写时,经验丰富的程序员会感到困扰,但话又说回来,main 是一种特殊的存在;)

              【讨论】:

                猜你喜欢
                • 2020-01-23
                • 2010-12-03
                • 1970-01-01
                • 2021-07-01
                • 2012-08-16
                • 2017-12-22
                • 2020-10-12
                • 2013-05-01
                • 1970-01-01
                相关资源
                最近更新 更多