为什么下面给出了从double ***到const double ***的转换错误

为什么它不能将double ***转换为const double ***

 void foo(const double ***d) { } int main (int args, char*[] args) { double ***d; /*initialize d */ foo(d); } 

如果你的C标记是可信的,gcc会生成一个警告,因为你的例子和const double * const * const * d的类型不同。 在C ++中,它是OP代码中的错误,但是slap-const-everywhere方法是合法的。

编译器警告您的原因是指向指针(或进一步间接)的指针允许通过修改参数指向的位置将指针返回给调用者。

如果指针的目标被声明为const,那么被调用的函数将期望它放在那里的值在返回时被视为const。

T**传递给const T**一个更简单的例子说明了为什么这是一个错误将是:

 void foo ( const char ** z ) { *z = "A"; } int main (int nargs, char** argv) { char* z = 0; char** d = &z; // warning in C, error in C++ foo ( d ); // bad - modifies const data z[0] = 'Q'; } 

C中的const意味着数据不会改变。 C ++中的const意味着数据不会公开更改 – C ++对象中的可变数据可能会发生变化。 AC编译器可以优化其代码,以便在某处缓存某些const数据,但由于可能的可变性,C ++编译器无法做到这一点,因此有一个较弱的限制,即您不能将const数据返回到非const,如上所述。 所以在C ++中, double***可以转换为const double * const * const * d因为额外的const阻止返回不可修改的内存,但是在C中,如果编译器优化重复访问,它会生成警告和可能的错误别处的记忆。

您可以在http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17找到您的问题的答案。

这意味着你应该使用const double * const * const * d

使用const_cast_operator()

出于相同的原因,对于**(指向指针的指针)也是如此。

此代码也会产生此错误,并且更清楚地看到编译器为什么不允许您在此处执行此操作:

  double d = 0.0; double * pd = &d; const double ** ppd = &pd; // <--- Error 

如果你能够做到这一点,你可以有一个'const'指针指向数据(ppd),你可以通过改变可变值d来改变它。 这违反了const,所以编译器不允许你这样做。

考虑d指向黑盒子的指针。

编译器可以将const添加到d本身或黑盒,但不能添加黑盒的内容。 所以

 void foo1(double ***d); /* ok, no casts needed */ void foo2(double *** const d); /* ok, no casts needed; const added to `d` itself */ void foo3(double ** const *d); /* ok, no casts needed; const added to the blackbox */ void foo4(double * const **d); /* oops, trying to change the insides of the blackbox */ void foo5(const double ***d); /* oops, trying to change the insides of the blackbox */ void foo6(double ** const * const d); /* ok: d is a constant pointer to a constant blackbox */ 

使用const double *** d只有d的值是const 。 在C中,从double aconst double * a的转换是合法的,而从double bconst double ** b (或进一步间接)的转换不是。

因此,要从double *** d转换为const double *** d2,您可以执行以下操作:

  双倍的;
   const double * b = ** d;
   const double ** c =&b;
   const double *** d2 =&c;

当然,由于非const的间接性, const double *** d的使用仍然值得怀疑。