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