为什么调用接受 (const char * const **) 和 char *** 的函数会引发 -Wcast-qual 标志?

Why does calling a function that accepts a (const char * const **) with a char *** raise a -Wcast-qual flag?

如果我们有 void foo(const char * const ** bar); 并且我们用 char *** bar = malloc(...); 调用它,例如 foo((const char * const **) bar); 它 returns:

error: to be safe all intermediate pointers in cast from ‘char ***’ to ‘const char * const**’ must be ‘const’ qualified [-Werror=cast-qual]

尝试在不转换的情况下传递它会导致类型警告,但将 char * 传递给 const char * works,我也可以传递一个char ***char ** const * 函数参数中,但我想要更多的只读限定符,而不仅仅是一个级别。

意图是函数假定整个指针数据和传入的指针都是只读的,这样指针就不会以任何方式被写入。

我知道这个标志是一个额外的标志,但它的定义是:

-Wcast-qual

Warn whenever a pointer is cast so as to remove a type qualifier from the target type. For example, warn if a const char * is cast to an ordinary char *.

据我所知,没有类型限定符被删除,而是我们添加类型限定符让用户知道该函数不会更改任何数据.

为什么前面提到的代码会触发额外的警告 -Wcast-qual? 是否有更好的方法来传递一个完全 malloc 的三重指针作为读取 -只有功能?

Why does passing a char* to a function that expects a char const* work?

这很容易理解。您无法修改被调用函数中的字符串。没关系。

Why does passing a char** to a function that expects a char const** not work?

这听起来不直观,但这是有原因的。用 int.

来类比
const int a = 10;
void foo(int const ** ap)
{
   *ap = &a;
}

void bar()
{
   int * p = NULL;
   foo(&p);
   *p = 20;
}

如果您被允许使用它,您可以在 bar 中间接修改 a,即 const

这就是为什么类型为 int**&p 不允许隐式转换为 int const** 的原因。

TL;DR: const char * const ** -> const char * const * const *

为了完成问题,/users/2410359/chux 在评论中回答(要求他们做一个 post,但他们没有)。解决方案是使用不触发 -Wcast-qual 标志的 const char * const * const *。基本上我所拥有的不是真正的只读限定符,我需要另一个级别。