在 main 函数中重命名 argc 和 argv 是否安全?

Is it safe to rename argc and argv in main function?

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

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

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

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

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

当然你可以安全地重命名这些参数

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

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


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

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

int main(int, char*[]);

如果您需要在实现中使用它们,实际上您需要为它们命名。使用哪个名称实际上是无关紧要的。

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

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

来自 C standard 的第 5.1.2.2.1 节:

The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:

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

or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):

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

or equivalent; or in some other implementation-defined manner

也就是说,使用 argcargv 以外的任何内容可能会使阅读您的代码的其他人感到困惑,因为他们习惯了这些参数的常规名称。所以最好在清晰度方面犯错。

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

不过,就我个人而言,我不会推荐它,因为传统的 argcargv 对所有可能使用过您的代码的其他 C 程序员来说是如此广为人知和熟悉。在漫长的 运行 中,使用你自己的、特殊的、不同的名字会在你的读者中引起更多的混乱 and/or 沮丧,而不是因为你更喜欢你的名字而拯救你。

"When in Rome, do as the Romans do."

名称 argcargv 实际上是 C++11 之前的 C++ 标准强制要求的。它说:

All implementations shall allow both of the following definitions of main:

int main ()

and

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

并继续讨论 argcargv 的要求。

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

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

All implementations shall allow both

  • a function of () returning int and
  • a function of (int, pointer to pointer to char) returning int

as the type of main (8.3.5). In the latter form, for purposes of exposition, the first function parameter is called argc and the second function parameter is called argv,…

就编译器而言是安全的。

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

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

但我认为我不需要说这将是多么糟糕的做法。

根据 C 标准,是的,您可以重命名,不会有任何影响。据我了解,在 C 语言中,默认的 Keyword/types/token 名称是用 purpose/usage 定义的,因此以相同的方式定义名称

argc --> argument count

argv --> argument vector

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

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

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

我的笔记:

最好遵循常见的 standards/code 风格,使代码更加可见和可读

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

#define yourCounterName argc
#define yourVectorName  argv 

你不会冒任何风险并产生 "clean solution"。

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

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

这个问题对我来说涉及到一般用代码表达英语的选择。您似乎对速记描述感到困扰,尤其是当速记显示相似的文本时。但是在您的示例中,将 argn 更改为 n_of_args 只会完成将一种类型的简写形式更改为另一种形式的 shorthand 而没有真正的附加值:澄清或其他可见属性。

单词 'number' 已被替换为字母 'n'。

如果您是通过反简写的理念来更改简写名称,那么这样的做法似乎更合适:

main( int argumentCount, char ** argumentVector )

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

有人会说名为 argumentCount 的变量被声明为 int 并且 Count 不能为负数但你可以有一个负数 int {unsigned is better}。

同样,它是什么以及如何使用在这种解释中发挥作用。如果它是一个计数,那么我认为它永远不会是负数。毕竟,你怎么能拥有 -2 个苹果。我会说,你欠两个苹果。如果它是一个数字,那么我希望可能出现负面情况。这就是附加词 'of' 可能对您很重要的原因。那,也许一个集合所引用的数字意味着一个特定的项目,而不是集合本身的 属性。即:argumentsNumber = 5 表示一个特定的参数但不是 numberOfArguments.

main( int maxArgumentsIndex, char ** arguments ).

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

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

void function( const unsigned int maxArgumentsIndex, const char ** arguments )

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

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