本文可能让你想起谭浩强, 那就这样吧.

“参数是 const int**, 我传入 int** 居然警告??”

代码

我们简化为赋值, 传参是一样的.

int main() {
  int** n2;
  const int** c2 = n2;

  int* n1;
  const int* c1 = n1;
}

使用 gcc 按照 C99 标准编译

$ gcc -ansi -Wpedantic -std=c99 test.c
test.c: In function ‘main’:
test.c:3:20: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
   const int** c2 = n2;
                    ^

可以看到, 第一个赋值出现了 “incompatible pointer” 而第二个没有.

原因

将类型形式化的写出来, 大概是

* n2: pointer_to(pointer_to(int))
* c2: pointer_to(pointer_to(const int))
* n1: pointer_to(int)
* c1: pointer_to(const int)

注意最开始的 const 修饰的是 int 而非指针.

相关的 C99 条款有

因此, 按照第 2 条, pointer_to(int) 可以被转换成 pointer_to(const int). 所以 c1 = n1 是允许的.

按照第 3 条, intconst int 并不 compatible, 因此按照第 1 条, pointer_to(int)pointer_to(const int) 不 compatible, 因此按照第 4 条, 赋值不允许, 因为 pointer_to(int)pointer_to(const int) 不 compatible. 所以 gcc 的报错信息是对的.