[英]About Warning Option "incompatible-pointer-types"
我的程序( https://godbolt.org/z/Y93eG7K7s ):
int main(){
int temp = 0;
int* tempp = &temp;
int** temppp = &tempp;
int*** tempppp = &temppp;
const int* intp0;
intp0 = tempp; // A
const int** intp1;
intp1 = temppp; // B
}
GCC 或 Clang 都可以編譯,但都在行 B中引發相同的“不兼容指針類型”警告。 我對那個警告沒意見,因為const int **
和int **
絕對是兼容指針類型中的兩個。 但是(在我看來), const int *
和int *
也是兩個兼容的指針類型( A行)。
因此我的問題是:為什么const int *
和int *
被認為是兼容的指針類型?
GCC 警告消息措辭不正確; intp1 = temppp
違反的規則不是=
的操作數必須兼容,而是它們必須符合某些約束。 兼容性是這些限制的一個因素,但它不是這里討論的因素,因此該消息具有誤導性。 盡管問題表明 Clang 提出了“不兼容的指針類型”警告,但我沒有看到這一點; Compiler Explorer 上可用的每個 Clang 版本都會報告一條正確的錯誤消息,“從 'int **' 分配給 'const int **' 會丟棄嵌套指針類型中的限定符。”
int *
可以分配給const int *
,因為簡單分配的規則允許向直接指向的類型添加限定符。 C 2018 6.5.16.1 說:
滿足以下條件之一:
……
— 左操作數具有原子、限定或非限定指針類型,並且(考慮左操作數在左值轉換后將具有的類型)兩個操作數都是指向兼容類型的限定或非限定版本的指針,並且左側指向的類型具有右邊指向的類型的所有限定符; ……
const int *
指向的非限定類型是int
, int *
指向的非限定類型也是int
,並且int
與自身兼容。 此外, const int *
const int
int int *
指向的類型int
的所有限定符。
相比之下, const int **
指向的非限定類型是const int *
,而int **
指向的非限定類型是int *
, const int *
不兼容int *
。 (請注意,雖然const int *
指向限定類型,但它本身是非限定的;類型const int *
的對象可能會更改為指向不同的const int
;它不是const
限定的。)所以intp1 = temppp
不滿足此約束,因此編譯器會發出警告。
不允許這樣做的原因是它可能導致指向限定類型的指針指向沒有該限定符的對象。 C 2018 6.5.16.1 6 給出了一個示例,此處顯示略有修改並帶有我的注釋:
const int *ipp;
int *p;
const int i = 1;
/* The next line violates the constraints because `&p` is an `int **`, and
it is assigned to a `const int **`.
For illustration, suppose we suspend the constraint and allow it.
*/
ipp = &p;
/* In the following, both `*ipp` and `&i` are `const int *`, so this is
an ordinary assignment of identical types.
*/
*ipp = &i;
/* In the following, `*p` is an `int`, to which an `int` is assigned. So
this is an ordinary assignment of identical types. However, `p` points
to `i`, which is `const`, so this assignment would change the value of
a `const` object. The assignment `ipp = &p` above enabled this, so it
is unsafe and should be disallowed.
*/
*p = 0;
因此我的問題是:為什么
const int *
和int *
被認為是兼容的指針類型?
它們不是兼容的指針類型。 如上所述,不允許賦值的原因是關於限定符的規則,而不是關於兼容類型的規則。
C 中兼容類型的概念不是關於一種類型是否可以分配給另一種類型,而是關於兩種類型是否實際上相同,除了我們不知道的部分。 例如,一個包含三個int
的數組和一個包含未指定數量的int
的數組是兼容的——我們所知道的關於這兩種類型的所有部分都是相同的。 如果未指定的部分已完成,它們可能相同。 類似地,返回void *
且采用未知參數的函數與返回void *
且采用某些已聲明參數的函數兼容。 這個兼容性問題與作業中的限定符問題無關。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.