2016-04-28 64 views
3

这是原型execv我可以传递一个const char *数组给execv吗?

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

我可以通过作为第二个参数的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; 
} 

编译时,GCC说,“从传递兼容的指针类型‘execv’的论点2:”如果我不使用投。

POSIX documentationexecv(中途理由部分),它看起来像第二个参数是为了向后兼容一个char *const数组:

argv[]envp[]是常数包含的语句,以向未来的作者明确表示这些对象是完全不变的语言绑定。 ...不幸的是,第四列不能使用...

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

这个(char **)可以放心使用吗?我应该创建一个char *数组并将其传递给execv而不是?

回答

1

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

那么,你已经知道你可以施展才能这样做。

从POSIX文档execv(中途原理部分),它看起来像第二个参数是为了向后兼容性char * const的数组:

我不会把它放在这些条款,但是,对选定的签名有一个兼容性方面。您引用的部分解释说,C没有完全令人满意的方式来表达const的程度 - POSIX要求execv()提供参数。 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 }); 

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

+0

不知何故,我认为字符串文字是'const char'。我认为,从我使用的变量中抽出“const”并不是那么糟糕,尽管我开始认为我误解了常量的正确性,或者它在C中并不总是实际可行的。 – yellowantphil

+0

@anaranjada ,不过,标准规定它们是'char'类型的数组,尽管在实践中它们可能是不可写的。 GCC可以选择使用'const char'数组来替代,以帮助您找到试图写入其中的地方 - 也许这正是您想要的。 (因为这个原因,当你启用该选项时'gcc'不合格。) –

+0

是的,我认为GCC选项让我失望。无论如何,我从代码中删除了一些'const'限定符,现在编译时没有警告。谢谢。 – yellowantphil

1

如果你只是抛弃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并不重要。

+0

是的,你敢,至少如果你愿意将你的陈述限制在* conforming *编译器。根据标准,字符串字面值对应于类型为(非''const')'char'的元素的静态数组。因此,您甚至不需要使用中间变量来形成数组初始值设定项。 –

相关问题