2009-09-10 14 views
2

爲什麼不能將double ***轉換爲const double ***爲什麼以下給我一個轉換錯誤從雙***到const雙***

void foo(const double ***d) 
{ 


} 


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

     foo(d); 

} 
+0

有一個標記爲C和C++的問題,當關於什麼是錯誤和允許的不同的規則會產生一些混淆。 – 2009-09-10 11:36:09

+0

@你是對的。我是這個例子的usigng C編譯器。這方面的規則真的不同嗎? – vehomzzz 2009-09-10 11:41:48

回答

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中,如果編譯器優化對其他位置的重複訪問,則會生成警告和可能的錯誤。

0
+0

這就是C++,問題是關於C – fortran 2009-09-10 11:50:46

+0

@fortran,問題最初被標記爲C和C++。這個問題本身並沒有說清楚哪一種語言正在被使用,因此混合使用C和C++的具體答案 – Glen 2009-09-10 11:54:00

0

出於同樣的原因,對於**(指向指針的指針)也是如此。

此代碼也會產生這個錯誤,這是更清晰的看到爲什麼編譯器不會讓你做到這一點的位置:

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

如果你能做到這一點,你可以有一個「常量」指向數據的指針(ppd),你可以通過改變可變值d來改變。這違反了const,所以編譯器不會讓你這樣做。

+1

這不是原因,因爲這是合法的:double d = 0; double const * pd =&d ;,它還允許您通過更改局部變量來更改「const」指針。 – me22 2009-09-10 17:11:49

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 */ 
0

隨着 const的雙*** dd的值是常量。在C從一個常量轉換雙*一個是合法的,同時從雙 b const的雙** b(或進一步間接)的轉化則不是。

因此從轉換雙皇冠d常量雙*** D2,你可以做到以下幾點:

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

當然使用常量雙皇冠d的由於非常量的間接性,這仍然值得懷疑。

相關問題