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

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吗?

Joh*_*ger 4

我可以传递一个 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)

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