在我工作的C / Unix环境中,我看到一些开发人员使用__progname
代替argv[0]
来获取使用消息。这有什么好处吗? __progname
和argv[0]
之间有什么区别。它是便携式的吗?
答案 0 :(得分:18)
__progname
不是标准的,因此不可移植,更喜欢argv[0]
。我想__progname
可以查找字符串资源以获取不依赖于您运行它的文件名的名称。但argv[0]
会为您提供他们实际运行它的名称,我会发现它更有用。
答案 1 :(得分:7)
使用__progname
可以在保持程序名称的同时更改argv[]
数组的内容。一些常用工具,例如getopt()
在处理参数时修改argv[]
。
为了便于携带,您可以在程序启动时strcopy argv[0]
进入您自己的progname
缓冲区。
答案 2 :(得分:6)
还有一个GNU扩展,因此可以从main()外部访问程序调用名称,而无需手动保存。但是,人们可能会手动做得更好;从而使其可移植而不是依赖于GNU扩展。不过,我在这里提供了可用文档的摘录。
来自the on-line GNU C Library manual(今日访问):
“许多没有从终端读取输入的程序被设计为在任何系统调用失败时退出。按照惯例,来自这样程序的错误消息应该从程序的名称开始,没有目录。你可以找到该名称在变量program_invocation_short_name
中;完整的文件名存储在变量program_invocation_name
。
变量:char * program_invocation_name
此变量的值是用于调用当前进程中运行的程序的名称。它与argv[0]
相同。请注意,这不一定是有用的文件名;通常它不包含目录名称。
变量:char * program_invocation_short_name
此变量的值是用于调用当前进程中运行的程序的名称,其中删除了目录名称。 (也就是说,它与program_invocation_name
相同,减去最后一个斜杠的所有内容,如果有的话。)
库初始化代码在调用main之前设置这两个变量。
可移植性注意:这两个变量是GNU扩展。如果希望程序与非GNU库一起使用,则必须在main中保存argv[0]
的值,然后自己删除目录名称。我们添加了这些扩展,以便编写自包含的错误报告子例程,而不需要主要的明确合作。“
答案 3 :(得分:4)
这是一种BSD主义,绝对不可移植。
答案 4 :(得分:4)
我发现argv [0]至少有两个潜在的问题。
首先,如果execve()调用者是邪恶或粗心的话,argv [0]或argv本身可能为NULL。调用execve(“foobar”,NULL,NULL)通常是一种简单而有趣的方式来证明一个过于自信的程序员,他的代码不是sig11-proof。
还必须注意,argv不会在main()之外定义,而__progname通常被定义为可以在usage()函数中使用的全局变量,甚至在调用main()之前(如非标准) GCC建设者)。
答案 5 :(得分:2)
__ progname只是argv [0],其他回复中的例子显示了使用它的弱点。虽然也不便携,但我在/ proc / self / exe(Linux,Android)上使用readlink,并且读取/ proc / self / exefile(QNX)的内容。
答案 6 :(得分:0)
如果您的程序使用例如符号链接运行,则argv [0]将包含该链接的名称。
我猜__progname将包含实际程序文件的名称。
在任何情况下,argv [0]由C标准定义。 __progname不是。