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


82

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

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

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

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


21
是的,完全安全。
David Hoelzer

55
正如所有答案所说,是的,这很安全。但是请不要那样做。每个人都知道argcargv是。n_of_args并且args可能会更清楚的人谁不知道C或C ++ -但是这不是你的听众。
基思·汤普森

4
可以执行此操作,但这还不够。每个人都知道它们是什么,他们确实希望它们像那样。
SergeyA 2016年

10
如果问题恰好是“如果我选择自定义名称,我会破坏某些东西”,那么确切的答案是“是,您会破坏已经建立好的传统”;)
Frax 2016年

12
翻转它们!..并从一开始就为工作安全打下基础:)
yano

Answers:


121

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

根据C标准的5.1.2.2.1节:

程序启动时调用的函数名为main。该实现没有为此函数声明任何原型。它的返回类型应为int且不带参数:

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

或者用两个参数(这里称为argc并且argv虽然可以使用任何名字,因为他们是当地在声明它们的功能):

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

或同等学历; 或以其他实现定义的方式

话虽这么说,使用比其他任何东西argc,并argv可能会混淆别人读你的代码谁是用来为这些参数的传统名称。因此,最好还是不要出神。


38

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

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

int main ()

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

然后讨论了argc和的要求argv

因此,从技术上讲,任何使用不同名称的程序都不符合标准,并且允许编译器拒绝它。当然,实际上没有编译器这样做。请参阅comp.std.c ++上的该线程,或此C ++ 03草案标准的3.6.1节。

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

所有实现都应允许

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

作为main(8.3.5)的类型。在后一种形式中,出于说明的目的,第一个功能参数被调用argc,第二个功能参数被称为argv,…


29

当然,你可以重命名这些参数,安全,只要你喜欢

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

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


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

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

 int main(int, char*[]);

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


5
正如您所说的,只有一些标识符是“写在沙滩上的”。函数名称肯定不是。
史蒂夫·考克斯

1
@SteveCox “函数名称肯定不是。” 最后他们是。沙粒的只是数字:-P ...
πάνταῥεῖ

3
好的,但认真。编译后,目标代码中仍包含函数名称。否则链接将无法正常工作
Steve Cox

4
@πάνταῥεῖ:除非您特别努力删除它们,否则函数名称的确会保留在最终的可执行文件中。
Nick Matteo

1
@Kundor:Windows上的链接之后,所有非特殊功能不保留的名字
达尼

15

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


7

是的,使用其他名称是安全的。

但是,就个人而言,我不推荐使用它,因为它是传统的,argc并且argv对于可能与您的代码一起工作的所有其他C程序员如此广为人知和熟悉。从长远来看,使用您自己的特殊的不同名称会给您的读者造成比以往更多的困惑和/或沮丧,因为您会更喜欢自己的名字,这将使您比以往更省钱。

“在罗马做到入乡随俗。”


但是,很少有明显的场景要求使用不同的名称,一个臭名昭著的场景是初始化GLUT,glutInit(&argc, argv)其中必须以不同的方式声明和初始化参数,以免让GLUT吃掉命令行参数,除非我们愿意。SO链接
user3078414 '16

@ user3078414有趣的示例,但是我看不到它如何说明必须命名的变量。根据另一个问题中的示例,我们可以轻松编写int dummyargc = 1; char *dummyargv[1] = {(char*)"Something"}; glutInit(&dummyargc, dummyargv);
史蒂夫·萨米特

谢谢,@ steve-summit。某些API文档碰巧是误导性的,因此,该线程对突出显示argc argv命名约定非常有帮助,您的贡献也非常有用。我只是将我的评论作为最好使用任何不同名称的示例。这是SO链接
2016年

5

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


3

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

通常,我觉得很少讨论选择的哲学,因此想对此事提供一个观点,因为我认为这对于要求这样做的原因很重要。

对我来说,这个问题涉及在一般情况下用代码表达英语的选择。似乎您对速记说明感到不安,特别是如果速记键落在外观相似的文本上。但是,在您的示例中,将argn更改为n_of_args只会完成将一种类型的速记方式更改为另一种形式的速记方式,而无需增加实际值:澄清或其他可见属性。

单词“ number”已被字母“ n”代替。

如果您通过反短手的手法来更改短手名,那么这样的事情似乎更合适:

main(int argumentsCount,char ** argumentsVector)

我一直在思考两件事:根据事物的本质和/或隐含的用法来命名事物。将其命名为argumentsVector对我来说是多余的,因为双重间接**隐含了作为矢量的属性。因此,我编写代码的更好的方法是:**参数。

有人会说名为argumentCount的变量被声明为int,并且Count不能为负,但是您可以具有负的int {unsigned is better}。

同样,它的含义和用法在此解释中起作用。如果是计数,那么我认为它永远不会是负数。毕竟,您怎么能拥有-2个苹果。我会说,你欠两个苹果。如果它是数字,那么我希望有一个否定的情况。这就是为什么附加词“ of”可能对您很重要的原因。那个,也许是集合所指的数字,意味着一个特定的项目,而不是集合本身的属性。即:argumentsNumber = 5表示一个特定的参数,但不包括numberOfArguments。

main(int maxArgumentsIndex,char ** arguments)。

这消除了歧义。将其称为索引可消除否定情况下的歧义,并描述其含义以及如何使用它。它也通过英语措辞暗示了max是一个绝对值,编写修改该值的代码(应该为const)会觉得很奇怪。“参数”在这里很有意义,因为它是复数形式,描述了它是什么,以及应该如何使用它。即使这样解释也可能很危险,因为Index是Count / NumberOf的-1。5个参数得出maxIndex为4!

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

无效函数(const unsigned int maxArgumentsIndex,const char ** arguments)

并非所有情况都需要长手描述符。实际上,有时候空手可以提高可读性,尤其是在编写数学类(例如Vec3f,矩阵,四元数等)的情况下……我几乎总是会尝试匹配数学语言而不是语言。 。浮动x,y,z vrs。float xComponent之类的。

我了解所有这些都是样式选择,但是从长远来看,意识到这些选择确实会有所帮助。我保证当数组不是以复数形式编写时,经验丰富的程序员会感到烦恼,但是再次,main是存在的一种特殊散文;)


2

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

argc --> argument count

argv --> argument vector

在用法上也很有意义,因此您可以更改为任何期望的名称 Reserved names

在GCC中,程序执行从函数名称开始 main并不取决于他的参数。

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

我的笔记:

最好遵循通用的标准/代码样式,以使代码更具可见性和可读性


0

就编译器而言,它是安全的。

这可能导致的唯一问题是混乱。读取您的代码的人会期望这两个变量具有其标准名称。您甚至可以执行以下操作:

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

但是我认为我不需要说出这种不良做法。


-1

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

#define yourCounterName argc
#define yourVectorName  argv 

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


这些不是常数,而只是替代。
大卫·邓纳姆
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.