yel*_*hil 5 c posix const const-correctness exec
这是原型execv:
int execv(const char *path, char *const argv[]);
Run Code Online (Sandbox Code Playgroud)
我可以传递一个const char指针数组作为第二个参数吗?
此示例程序在USE_CAST未设置时发出警告:
#include <unistd.h>
int main(int argc, char *argv[])
{
if (argc > 0) {
const char *exe_name = "/bin/echo", *message = "You ran";
const char *exe_args[] = { exe_name, message, argv[0], NULL };
#ifdef USE_CAST
execv("/bin/echo", (char **) exe_args);
#else
execv("/bin/echo", exe_args);
#endif
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在编译时,gcc说,"如果我不使用强制转换,则从不兼容的指针类型传递'execv'的参数2".
从POSIX文档为execv(中途理由部分),它看起来像第二个参数是char *const为了向后兼容数组:
包含有关
argv[]和envp[]成为常量的语句,以明确未来的语言绑定编写者,这些对象是完全不变的.......遗憾的是,第四列无法使用......
"第四栏"所指的地方const char* const[].
是(char **)投安全在这里使用?我应该创建一个char *数组并将其传递给它execv吗?
我可以传递一个 const char 指针数组作为第二个参数吗?
嗯,是的,您已经知道您可以进行投射来做到这一点。
从 execv 的 POSIX 文档(基本原理部分的一半)来看,第二个参数似乎是一个 char *const 数组,仅用于向后兼容:
我不会用这些术语来表达,但是,是的,所选签名存在兼容性方面的问题。您引用的部分解释了 C 没有完全令人满意的方式来表达constPOSIX 要求execv()为参数提供的程度。POSIX 保证该函数不会更改其中的指针argv或它们指向的字符串。
在这种情况下,我认为argv按照您建议的方式强制转换指针并非不合理,尽管我会在代码中留下注释,解释为什么这样做是安全的。
另一方面,您应该考虑简单地保留const数组声明:
char *exe_name = "echo", *message = "You ran";
char *exe_args[] = { exe_name, message, argv[0], NULL };
Run Code Online (Sandbox Code Playgroud)
或者,在您的简单示例中,即使这样也可以:
char *exe_args[] = { "echo", message, argv[0], "You ran", NULL };
Run Code Online (Sandbox Code Playgroud)
C 字符串文字对应于 类型的数组char,而不是类型的数组const char,因此就 C 而言,这是完全合法的,即使实际尝试修改这些字符串的内容可能会失败。
第三,现代 C 有数组文字,所以你甚至可以这样做:
execv("/bin/echo", (char *[]) { "echo", "You ran ", argv[0], NULL });
Run Code Online (Sandbox Code Playgroud)
在最后一种情况下,您甚至没有强制转换(类似于强制转换的东西只是数组文字语法的一部分)。