如何在C++中声明指向常量的指针指针?

3
我将尝试编写一个函数来解析命令行参数。以下是函数声明:
void parse(int, char const **);

以防万一,我也尝试过使用 (const char)**const char **cchar ** 并使用 typedef const char cchar. 然而,如果我将 char ** 传递给该函数,如下所示:

代码为:

function(const char** data) { //do something } char** myData; function(myData);

所有这些尝试都会导致错误(因为它们应该是相同的),这是意料之中的。

void main(int argc, char **argv) {
    parse(argc, argv);

GNU编译器显示的错误是error: invalid conversion from 'char**' to 'const char**',而Clang显示的错误是candidate function not viable: no known conversion from 'char **' to 'const char **' for 2nd argument
有人建议采用声明指向常量字符的指针的指针(const char * const *)等解决方案,但我不希望任一指针为常量,因为我想能够修改指针,以便使用for(; **argv; ++*argv)循环一个参数。我如何声明“非常量指针的非常量指针,指向常量字符”?

7
C和C++是不同的编程语言,你需要选择其中一种。你可以尝试使用char*const*这样的语法,但是main函数应该声明为int main(int argc, char**argv); - Basile Starynkevitch
2
在您的情况下,只有数据是“const”。指针仍然可变。您可以使用parse(argc, const_cast<char const **>(argv))将其转换为“const”。 - Henri Menke
2
从char到const char的隐式转换 - BLUEPIXY
5
我原本认为所有没有警告的C代码都是有效的C++代码。-- 实际上并非如此。例如,在C语言中,不需要对malloc()的结果进行强制类型转换,但在C++中这样做就无法编译。 - ad absurdum
3
同样的代码在C语言和C++语言中可能是正确的,但在每种语言中执行的结果可能不同。(三目运算符的结合性就是一个例子) - M.M
显示剩余6条评论
2个回答

7
函数应该声明为:
void parse(int, char const * const *);

在C++中,char **可以在所有指针深度上隐式添加const,因此您可以将其称为parse(argc, argv)

在C语言中,const只能在第一个指针深度上添加(这是该语言的设计缺陷)。这里有一个专门的讨论帖子。因此,您必须这样调用函数:parse(argc, (char const * const *)argv);不幸地是。


5

最安全的签名是防止修改参数的同时允许任何其他const组合调用函数:

parse(int argc, char const* const* argv);

这意味着argv是一个指向const char常量指针常量指针

你可以像这样愉快地迭代参数:

for(auto arg = argv + 1; *arg; ++arg)
{
    if(!std::strcmp(*arg, "--help"))
        return print_help();
    else if(!std::strcmp(*arg, "-v") || !std::strcmp(*arg, "--verbose"))
        verbose_flag = true;
    // ... etc...
}

注意不需要接受变量int argc,因为字符数组的数组是以空终止符结尾的。

所以我通常使用这个:

struct config
{
    // program options and switches
};

config parse_commandline(char const* const* argv);

argv保证以NULL结尾吗?我不知道这个事实。那么,如果是这样的话,为什么需要argc作为参数呢? - Dead Beetle
@DeadBeetle 是的,这在标准中。 - Galik

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