关于警告选项 "incompatible-pointer-types"

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 ** 绝对是两个 in 兼容的指针类型。然而(在我看来),const int *int *也是两个in兼容的指针类型(line A)。

因此我的问题是:为什么const int *int *被认为是兼容的指针类型?

GCC 警告消息措辞不正确; intp1 = temppp 违反的规则不是 = 的操作数必须兼容,而是它们必须符合某些约束。兼容性是这些约束中的一个因素,但它不是这里讨论的因素,因此错误消息具有误导性。尽管问题表明 Clang 提出了“incompatible-pointer-types”警告,但我没有看到这一点; every version of Clang available on Compiler Explorer 报告正确的错误消息,“从 'int **' 分配给 'const int **' 会丢弃嵌套指针类型中的限定符。”

可以将 int * 分配给 const int *,因为简单分配的规则允许将限定符直接添加到 pointed-to 类型。 C 2018 6.5.16.1 说:

One of the following shall hold:

— the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right; …

const int *指向的不合格类型是intint *指向的不合格类型也是intint是与自身兼容。此外,const int * 指向的类型 const 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 **`.  Suppose it is allowed.
*/
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;

Therefore My Question is: Why const int * and int * are considered as compatible pointer types?

它们不是兼容的指针类型。如上所述,不允许赋值的原因是关于限定符的规则,而不是关于兼容类型的规则。

C 中兼容类型的概念不是关于一种类型是否可以分配给另一种类型,而是关于两种类型是否实际上相同,除了我们不知道的部分。例如,三个 int 的数组和一个未指定数量的 int 的数组是兼容的——我们对这两种类型的所有了解都是相同的。如果未指定的部分已完成,它们可能相同。类似地,返回 void * 且采用未知参数的函数与返回 void * 且采用某些已声明参数的函数兼容。此兼容性问题与作业中的限定符问题无关。