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

时间:2009-09-10 11:27:09

标签: c

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

void foo(const double ***d)
{


}


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

       foo(d);

}

6 个答案:

答案 0 :(得分:8)

如果要相信您的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数据返回到非 - 如上所述。因此在C ++中,double***可以转换为const double * const * const * d,因为额外的const会阻止返回不可修改的内存,但是在C中,如果编译器优化重复,它会生成警告和可能的错误访问其他地方的内存。

答案 1 :(得分:2)

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

找到

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

答案 2 :(得分:0)

答案 3 :(得分:0)

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

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

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

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

答案 4 :(得分:0)

考虑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 */

答案 5 :(得分:0)

const double *** d 只有 d 的值为常量的。在C中,从 a const double * a 的转换是合法的,而从双转换 b const double ** b (或进一步的间接)不是。

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

  double*** d;
  const double* b = **d;
  const double** c = &b;
  const double*** d2 = &c;

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