'char **' 和 'const char **'的兼容性問題

有時候必須非常專注的閱讀ANSI C 標準才能找到某個問題的答案。一位銷售工程師把下面的代碼作爲測試例子發給SUN的編譯器小組。

#include<stdio.h>

void foo( const char **P )

{}

 

int main( int argc, char **argv )

{

    foo( argv );

    return 0;

}

 

在VC6.0下編譯這段代碼,編譯器會發出警告:

cannot convert parameter 1 from char ** to const char **

 

提交代碼的工程師想知道爲什麼會產生類似的警告,他認爲,實參char *s 與形參 const char *p 應該是相容的,標準庫中所有的字符串處理函數都是這樣的。那麼,爲什麼實參 char **argv 與形參 const char **P實際上不能相容呢?答案是肯定的,它們並不相容。現在我們回顧一下標準中有關簡單賦值的部分,它位於ANSI C 第<st1:chsdate isrocdate="False" month="12" w:st="on" islunardate="False" day="30" year="1899">6.3.16</st1:chsdate>.1節,描述了下列約束條件:

要使上述賦值形式合法,必須滿足下列條件之一:

兩個操作數都是指向有限定符或無限定符的相容類型的指針,左邊指針所指向的類型必須具有右邊指針

所指向類型的全部限定符。

正是這個條件,使得函數調用中實參char*能夠與形參const char*匹配。它之所以合法,是因爲在下面的代碼中:

char *cp;

const char *cpp;

cpp = cp;

左操作數是一個指向有const限定符的char的指針;

右操作數是一個指向沒有限定符的char的指針;

char類型和char類型是相容的,左操作數所指向的類型具有右操作數所指向類型的限定符(無), 再加上自身的限定符 const (注意反過來不能賦值)。

 

標準第6.3.16.1節沒有說明char **實參與const char **形參是否相容。標準6.1.2.5節中講述實例的部分聲稱:const float * 類型並不是一個有限定符的類型,它的類型是“指向一個具有const限定符的float類型的指針”,也就是說const限定符是修飾指針所指向的類型, 而不是指針。類似地,const char **也是一個沒有限定符的指針類型,它的類型是“指向有const限定符的char類型的指針的指針”。 由於char ** 和const char ** 都是沒有限定符的指針類型,但它們所指向的類型不一樣(前者指向char *,後者指向 const char *),因此它們是不相容的。因此類型爲char **的實參和類型爲 const char **的形參是不相容的,編譯器會產生一條診斷信息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章