"argv[0] = name-of-executable" 是一个被接受的标准还是只是一种常见的约定?
在*nix类型的系统中,使用exec*()调用时,argv[0]将是调用者在exec*()调用中放置在argv0位置的内容。shell使用这个约定来表示程序名,大多数其他程序也遵循同样的约定,所以argv[0]通常是程序名。
但是,一个不受限制的Unix程序可以调用exec()并将argv[0]设置为任何它想要的值,所以无论C标准怎么说,你不能百分之百地依赖这个。
这个回答比paxdiablo在上面的回答更好。标准只是称之为"程序名",但是在我所知道的地方没有强制执行。Unix内核一致地将传递给execve()的字符串原封不动地传递给子进程。
C标准在它能够说的范围内是有限制的,因为它不知道'execve()'等函数。POSIX标准(opengroup.org/onlinepubs/9699919799/functions/execve.html)有更多的说法,明确指出argv[0]中的内容取决于执行'execve()'(或相关)系统调用的进程。
你可以有自己的观点,但是你关于强制执行的说法是错误的。如果一个实现不遵循标准,那么它是不符合标准的。事实上,由于"程序名"是实现定义的,像UNIX这样的操作系统只要指定了名字,就是符合标准的。这包括通过在exec系列调用中加载任何你想要的内容来明显伪造程序名。
这就是标准中使用"表示"这个词时的优势,当它引用argv[0]("它表示程序名")和argv[1..N]("它们表示程序参数")。"unladen swallow"是一个有效的程序名。
不仅是不受限制的Unix程序这样做,例如sendmail也会更改argv[0]来传达其状态:askubuntu.com/questions/868742
原因:该问题的出现是因为对于argv[0]的值是程序名还是可执行文件名存在疑问和不确定性。
解决方法:需要查阅ISO C11标准文档以获取确切的答案。根据ISO C11标准,如果argc的值大于零,那么argv[0]指向的字符串表示程序名;如果主机环境中无法获得程序名,argv[0][0]将是空字符。因此,argv[0]只是程序名的一种表示,并不一定就是程序名本身。ISO C11标准还规定,如果argc的值大于零,那么数组成员argv[0]到argv[argc-1]将包含指向字符串的指针,这些指针在程序启动之前由主机环境赋予实现定义的值。
这意味着如果主机环境不提供程序名,那么程序名可能为空;如果主机环境提供程序名,那么程序名可以是任何其他值,只要这些值能够表示程序名。然而,根据ISO标准,实现定义具有特定的含义,即实现必须记录其工作原理。即使是UNIX,在使用exec系列调用时也必须(而且确实)记录如何处理argv[0]。
因此,虽然ISO C11标准规定了argv[0]表示程序名,但并没有明确定义程序名的含义,特别是并不一定是可执行文件名。实现可以自由决定argv[0]的值,包括允许其中存储的内容不是实际的程序名。在实际编程中,不能指望argv[0]的值是可靠的。