拿走,例如execve(2),根据posix有这个原型[1]:
int execve(const char *path, char *const argv[], char *const envp[]);
对我来说,好像好像是
int execve(const char *path, const char *const argv[], const char *const envp[]);
会有明显的改善。
那么,有谁知道为什么会这样?什么可以解释需要 可能操纵给定的argv / envp字符串?
[1] http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html
答案 0 :(得分:2)
argv
的{{1}}和envp
参数不是指向execve()
的指针,以保持与在const
之前编写的有效C代码的向后兼容性。已添加到C。
C首先出现in 1972。后来,const
被添加到C in 1987.
为了保持与const
之前的代码的兼容性,const
的{{1}}更新声明必须能够接受非const
的输入。 C不允许从execve()
到const
进行分配。可以通过尝试(但失败)编译以下程序来验证这一点:
char *[]
因此,const char *[]
是最严格的类型,它与之前的void foo ( const char * argv[] ) { return; }
void main ( int argc, char * argv[] ) { foo ( argv ); }
代码向后兼容。
该问题提供了指向char *const[]
的POSIX文档的链接。链接的POSIX文档确实对此进行了如下解释:
关于
const
和execve()
是常量的语句包括到 向未来的语言绑定作者明确 对象是完全恒定的。由于ISO C的限制 标准,就不可能在标准C中陈述该想法。
实际上,确切地说:不可能以与{argv[]
以前的代码向后兼容的方式声明该想法。
...为
envp[]
和const
指定两个级别的const
-资格 exec 函数的argv[]
参数似乎很自然 选择,因为这些函数不会修改 指针或函数指向的字符,但这 会禁止现有正确的代码。相反,只有 指针被标记为常量。分配兼容性表 源自ISO C标准的 dst = src 总结了 兼容性:envp[]
由于所有现有代码...
表示将 dst: char *[] const char *[] char *const[] const char *const[]
src:
char *[] VALID - VALID -
const char *[] - VALID - VALID
char * const [] - - VALID -
const char *const[] - - - VALID
添加到C之前存在的所有代码。
...具有与第一行匹配的源类型, 提供最有效组合的列是第三列。的 仅有的其他可能性是第四列,但使用它会 需要对
const
或argv
参数进行强制转换。不幸的是 不能使用第四列,因为声明是非专家 自然会使用第二行中的那个。
答案 1 :(得分:0)
这基本上是由于C标准中的漏洞阻止了从T **
到const T * const *
的隐式转换。这样的转换是安全的(从T**
到const T **
的转换是有问题的),但是标准尚未进行更新以允许它。
mpb报价
包含有关argv []和envp []为常量的声明,以便将来向语言绑定的作者明确说明这些对象是完全恒定的。由于ISO C标准的局限性,因此无法在标准C中陈述该想法。
这意味着当/如果C标准已更新,则POSIX标准将被更改。
答案 2 :(得分:-1)
某些程序操纵argv字符串,以便ps
输出显示一些状态信息。例如:
root 6550 10809 0 13:10 ? 00:00:00 pure-ftpd (IDLE)
root 32216 1 0 Apr05 ? 00:00:00 vtund[s]: waiting for connections on port 5000
1023 30448 9847 0 09:01 ? 00:00:01 imap [username 192.168.1.135]
因此argv值不是常量,不应该这样声明。