我可以将const char *数组传递给execv吗?

这是execv的原型:

 int execv(const char *path, char *const argv[]); 

我可以传递一个const char指针数组作为第二个参数吗?

此示例程序在未设置USE_CAST时发出警告:

 #include  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; } 

在编译时,gcc说,“如果我不使用强制转换,则从不兼容的指针类型传递’execv’的参数2”。

execv的POSIX文档 (在Rationale部分的中间),看起来第二个参数是char *const数组,仅用于向后兼容:

关于argv[]envp[]是常量的声明是为了使未来的语言绑定编写者明确表示这些对象是完全不变的。 ……遗憾的是,第四栏无法使用……

其中“第四列”是指const char* const[]

(char **)演员在这里使用安全吗? 我应该创建一个char *数组并将其传递给execv吗?

我可以传递一个const char指针数组作为第二个参数吗?

是的,你已经知道你可以施展以便这样做。

从execv的POSIX文档(在Rationale部分的中间),看起来第二个参数是char * const数组,仅用于向后兼容:

我不会用这些术语来表达,但是,是的,所选签名存在兼容性方面。 您引用的部分解释了C没有完全令人满意的方式来表达POSIX要求execv()提供参数的const 。 POSIX保证函数不会改变argv的指针或它们指向的字符串。

在这种情况下,我认为按照你的建议投射argv指针并不是不合理的,尽管我会在我的代码中留下一条评论,解释为什么这样做是安全的。

另一方面,您应该考虑简单地从您的数组声明中const

 char *exe_name = "echo", *message = "You ran"; char *exe_args[] = { exe_name, message, argv[0], NULL }; 

或者,在您的简单示例中,即使这样做也会:

 char *exe_args[] = { "echo", message, argv[0], "You ran", NULL }; 

C字符串文字对应于char类型的数组,而不是const char ,因此就C而言,这是完全合法的,即使实际尝试修改这些字符串的内容可能会失败。

第三方面,现代C有数组文字,所以你甚至可以这样做:

 execv("/bin/echo", (char *[]) { "echo", "You ran ", argv[0], NULL }); 

在最后一种情况下,你甚至没有一个强制转换(类似于一个的东西只是数组文字语法的一部分)。

如果你只是要抛弃const ,那么你就不应该使用const来开始。 大多数(我敢说所有)编译器都会接受以下代码

 char *exe_name = "/bin/echo"; char *message = "You ran"; char *exe_args[] = { exe_name, message, argv[0], NULL }; execv( exe_args[0], exe_args ); 

如果这对你来说不够迂腐,那么另一种选择就是

 char exe_name[] = "/bin/echo"; char message[] = "You ran"; char *exe_args[] = { exe_name, message, argv[0], NULL }; execv( exe_args[0], exe_args ); 

请注意, execv将创建字符串的副本(为可执行文件创建argv数组),因此字符串实际上是否为const无关紧要。