为什么我不能将类型为'char* const *'的参数传递给一个期望'const char* const*'作为其参数的函数?

4

我正在编写一个使用 fork 和 execv 替代项目中的 system()popen() 的函数。 我发现虽然 execv 不会更改命令数组的内容,但它将其第二个参数声明为char * const argv[],这实际上可以更改 char* 的内容。因此,我决定像这样声明我的函数:int execute_cmd(const char* const cmd[]),既使指向 char 的指针是 const,也使 const 指针所指向的内容是 const(对不起,我知道这种状态很令人困惑,但我尽力了)。 然而,当我以这种方式调用它时:

void execute_cmd(const char* const cmd[])
{
    for (int i = 0; cmd[i]; i++)
    {
        printf("%s ", cmd[i]);
    }
}

int main()
{
    char* const cmd[] = {"ls", "-al", 0};
    execute_cmd(cmd);
    return 0;
}

出现了编译错误,提示如下:

test.c:21: 警告: 从不兼容的指针类型传递参数 1 给 ‘execute_cmd’

test.c:10: 注意: 预期 ‘const char * const*’ 类型的参数,但实参的类型是 ‘char * const*’

我想知道为什么会发生这种情况,因为在我的看法中,带有 const 的形式参数可以将非 const 变量作为其实际参数,例如:

void printInt(const int);
//which can call like this
int a=10;
printInt(a);

我认为用非常量变量初始化常量变量是非常常见的,那么这个函数为什么可以工作,但我的execute_cmd()却没有工作?我是否忽略了一些重要的内容?这个const有关吗?
我搜索了"char * const * and const char* const *" 以及 "const formal argument with non-const actual parameter" 这样的东西,但没有得到很有用的东西。如果有人能给出一个关于这个问题的正确关键字,我也将不胜感激。
我不是一个英语母语者,所以如果有语法问题,请原谅我。

1
@chux-ReinstateMonica 是的,它应该是 char * const cmd[],我写错了。 - Eric
1
换句话说,如果我试图在C++代码中调用它,并且命令或参数的一部分是字符串,当像char* const cmd[] = {ls_string.c_str(), al_string.c_str(), 0}这样初始化时,不会起作用,因为c_str()返回一个const char*。 - Eric
1
期望类型为“const char * const *”,但实参的类型为“char const”。这与代码中的“char * const cmd”和“char * const cmd[]”不一致。请提供真实的代码和真实的错误信息。避免拼写错误,使用剪切/粘贴功能。 - chux - Reinstate Monica
1
@TomKarzes 谢谢,当我搜索时,我发现了你提到的答案并看到了示例,但我的问题与那个稍有不同:char **char * const * 之间的区别将使得示例中的步骤4无法更改const指针。 - Eric
2
@chux-ReinstateMonica已经发布了最小化代码可能会导致问题的消息,并且真实反映了gcc的信息。 - Eric
显示剩余6条评论
1个回答

1
我想知道为什么会出现这种情况,因为带有const的形式参数可以将非const变量作为其实际参数。更准确地说,“带有const的形式参数可以将非const变量作为其实际参数。”const char * const cmd_paramter[]类似于“指向常量字符的常量指针数组”。char * const cmd_argument[]是一个“指向字符的常量指针数组”。请注意,数组元素的类型不同:const char *char *。在简单代码中也存在相同的问题:“预期为'char *',但实参的类型为'const char *'”。
void foo(char *bob);
const char *alice = "Alice";

// Bad, as `foo()` needs to be able to write `*bob`, yet alice point to `const` data.
foo(alice);  

此外,cmd 数组元素应该是 const char * 类型,以防止写入一个字符串字面值。
    // char* const cmd[] = {"ls", "-al", 0};
    const char* const cmd[] = {"ls", "-al", 0};

1
“同样问题,更简单的代码”代码示例是不相关的。提问者显然知道不能将const赋值给非const;问题是关于相反的方向。我认为你回答的第二部分是迄今为止最好的建议:如果可能的话,使所有内容都是const。 - Ruud Helderman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接