在主函数中重命名 argc 和 argv 是不是安全?

Posted

技术标签:

【中文标题】在主函数中重命名 argc 和 argv 是不是安全?【英文标题】: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++ 的人来说可能更清楚——但那不是你的听众。 可以这样做,这样做的理由还不够。每个人都知道这些是什么,并且他们确实希望它们是那样的。 如果问题恰好是“如果我选择自定义名称,我会破坏某些东西吗”,而不是精确的答案是“是的,你会破坏良好的传统”;) 翻转它们! .. 从一开始你就为工作保障奠定了基础:) 【参考方案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 是一种特殊的存在;)

【讨论】:

以上是关于在主函数中重命名 argc 和 argv 是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章

函数检查 argc 和 argv cs50。

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

带有自定义 argc 和 argv 的 getopt_long() 函数

main (int argc,char *argv[])

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

argc 和 argv 用于除 main 以外的函数