GCC下“initializing ‘char **’ with an expression of type ‘const char **’ discards qualifiers in nested pointer types”警告解讀

我曾經被這個警告困擾了好久好久,問了好些人,都說沒遇到過=_=…
問題程式碼片段(與問題無關的程式碼塊已被忽略):

size_t MyConv(const char *orginStr, const char *targetStr, ...) {
    char **tmpIn = NULL;
    char **tmpOut = NULL;
        ...
        ...
    tmpIn = &orginStr;
    tmpOut = &targetStr;
        ...
        ...
}

GCC編譯後會彈出如下警報:

sfind.c:887:8: warning: assigning to 'char **' from 'const char **' discards qualifiers in nested pointer types
      [-Wincompatible-pointer-types-discards-qualifiers]
        tmpIn = &orginStr;
              ^ ~~~~~~~~~

這條警告資訊翻譯出來是“用型別表示式初始化“char \**” “const char \**”丟棄巢狀指標型別中的限定符。 ”,個人表示很晦澀難懂。。。
後來翻閱《C專家程式設計》的時候,偶然間發現一個章節是討論const限定符的,認真看了下,頓時感慨自己學識太過淺薄。
上面的程式碼中,實參const char \*orginStr的const是修飾char orginStr的,而char **tmpOut是指向char *型別變數的一個指標(此“char *”型別無修飾符),這兩點倒是沒有疑惑。但當二者互相賦值的時候,const char *orginStrchar \**tmpOut這兩個指標所指向的型別的修飾符不同。一個是const char orginStr,帶了const修飾符,而另一個則是char *tmpOut,並沒有const修飾符。指標變數賦值時,賦值語句左邊的指標所指向的型別必須具有賦值語句右邊的型別所擁有的全部修飾符,才能正常透過編譯,否則就會捨棄右邊變數多餘的修飾符。

以下內容摘自ANSI C標準手冊

兩個運算元都是指向有限定符或無限定符的相容型別的指標,左邊指標所指向的型別必須具有右邊指標所指向型別的全部限定符。

也就是說:

int *a = NULL;
const int *b = a;

上面這段程式碼是可以正常透過編譯的,因為賦值語句左邊的指標指向的資料型別擁有了右邊的資料型別的所有修飾符(甚至還比右邊的多了一個const)而下面這段卻不行。

const int *a = NULL;
int b = a;

Leave a Reply

Your email address will not be published. Required fields are marked *

Captcha Code