const导致不兼容的指针类型。 为什么只有双指针?

这里已经解决了这个问题。

建议的副本和当前给出的答案没有解决为什么首先给出的示例没有问题。 主要是为什么没有推理:

const int ** is a pointer to const int *const int ** is a pointer to const int *不同”

也适用于:

const int * is a pointer to const intconst int * is a pointer to const int只是一个不同的东西”


我从不同的角度接近它,希望得到另一种解释。

带有示例的代码。

 #include  void f_a (int const a){ /* * Can't do: * a = 3; //error: assignment of read-only parameter 'a' * * Explanation: I can't change the value of a in the scope of the function due to the const */ printf("%d\n", a); } void f_ptr_a_type1 (int const * ptr_a){ /* * Can do this: * ptr_a' = 0x3; * which make dereferencig to a impossible. * printf("%d\n", * ptr_a'); -> segfault * But const won't forbid it. * * Can't do: * *ptr_a' = 3; //error: assignment of read-only parameter '* ptr_a' * * Explanation: I can't change the value of a by pointer dereferencing and addignment due to the int const */ } void f_ptr_a_type2 (int * const ptr_a){ /* * Can do this: * *a = 3; * * Can't do: * ptr_a = 3; //error: assignment of read-only parameter 'ptr_a' * * Explanation: I can't change the value because the const is protecting the value of the pointer in the funcion scope */ } void f_ptr_ptr_a (int const ** ptr_ptr_a){ /* * Can do this: * ptr_ptr_a = 3; * * ptr_ptr_a = 0x3; * * Can't do: * ** ptr_ptr_a = 0x3; //error: assignment of read-only parameter '**ptr_a' * * Explanation: Makes sense. Just follows the pattern from previous functions. */ } int main() { int a = 7; f_a(a); int * ptr_a = &a; f_ptr_a_type1(&a); f_ptr_a_type2(&a); int ** ptr_ptr_a = &ptr_a; f_ptr_ptr_a(ptr_ptr_a); //warning: passing argument 1 of 'f_ptr_ptr_a' from incompatible pointer type [-Wincompatible-pointer-types] } 

接受的广泛接受的答案是这样的:

int **与const int **不同,你无法安全地投射它

我的问题是为什么这个function突然关注

这里没有抱怨int不是int const

 int a = 7; f_a(a); 

它没有在这里抱怨因为int *既不是int const *也不是int * const

 int * ptr_a = &a; f_ptr_a_type1(&a); f_ptr_a_type2(&a); 

但突然间,它开始在双指针案件中抱怨。

  • 使用这个术语和示例寻找解释?

  • 为什么函数突然开始担心对她的范围之外的东西的写权限?

char *const char *转换始终是安全的。 通过const char * ,指向的数据无法修改,就是这样。

另一方面,从char **const char **的转换可能不安全的 ,因此不允许隐式。 请考虑以下代码,而不是解释它:

 void foo(const char **bar) { const char *str = "test string"; *bar = str; // perfectly legal } int main(void) { char *teststr[] = {0}; foo((const char **)teststr); // now teststr points to a `const char *`! *teststr[0] = 'x'; // <- attempt to modify read-only memory // ok in this line, there's no const qualifier on teststr! } 

如果在调用foo()时从char **const char **的转换是隐式的,那么你将有一种隐式转换const

该语言不允许不安全的转换,即将指针指向const -object转换为指向非const对象。

它并不关心安全转换,即那些你应用更严格的const限定条件而不是传递的东西。 例如,在对象真正可写的情况下,但是您将其传递给只需要读取它的函数,就没有任何抱怨的目的。

你的例子显示后者:

 f_ptr_a_type1(&a); 

这说‘采用我声明非const的这个intconst视图’

 f_ptr_a_type2(&a); 

这只是说‘这是指向同一个非const int的指针,你将获取该指针的副本,它将是函数体内的const (指针,而不是int )’

至于那个错误:

 f_ptr_ptr_a(ptr_ptr_a); 

这是由一些程序员老兄所说的:引用的类型是不同的,而C / C ++允许传递指针到const ,其中指向非const指针,它不会“级联”转换通过不止一个级别的指针,因为这可能是不安全的,因为菲利克斯帕尔曼已经说明了。

让我们分解一下:

  • const int **是指向const int *的指针。

  • int **是指向int *的指针。

换句话说, const int **是指向一个东西的指针,而int **是指向不同东西的指针。

为什么函数突然开始担心对她的范围之外的东西的写权限?

投诉不是来自function参数的观点。 该参数在函数范围内的行为与预期的一样,并且在变量进入函数范围之前不会受到变量的影响。

 void f_ptr_ptr_a (int const ** ptr_ptr_a){ /* * Can't do: * ** ptr_ptr_a = 3; //error: assignment of read-only parameter '**ptr_a' */ } 

int const ** ptr_ptr_a输入由值复制的函数作用域,不允许更改** ptr_ptr_a 。 一旦它们被值复制,该错误与变量的含义无关。

由于函数调用期间发生隐式转换而产生错误。 解析调用f_ptr_ptr_a(ptr_ptr_a); 我们得到:

 int const ** ptr_ptr_x = ptr_ptr_a; //This line causes the warning f_ptr_ptr_a(ptr_ptr_x); 

使用这个术语和示例寻找解释?

现在让我们将这个例子剥离到基本的基础上。

 int main() { int a = 3; int * ptr_a = &a; int ** ptr_ptr_a = &ptr_a; // I promise here **ptr_ptr_a will always be the same int const b = 5; int const * ptr_b = &b; int const ** ptr_ptr_b = &ptr_b; ptr_ptr_b = ptr_ptr_a; // Warning here: -Wincompatible-pointer-types-discards-qualifiers printf("%d\n", ** ptr_ptr_b); // Look at me, I've just changed the value of const ** int. ** ptr_ptr_a = 15; printf("%d\n", ** ptr_ptr_b); // I did it again. } 

由于隐式转换,编译器警告我们。

 int main() { int const a = 3; int const * ptr_a = &a; int const ** ptr_ptr_a = &ptr_a; // I promise here **ptr_ptr_a will always be the same int const b = 5; int const * ptr_b = &b; int const ** ptr_ptr_b = &ptr_b; ptr_ptr_b = ptr_ptr_a; printf("%d\n", ** ptr_ptr_b); // Look at me, I've just changed the value of const ** int. // And there were no warnings at all. Har har har har! } 

我可以从这个问题中得出一个结论,从目前的角度来看,它引入了不必要的复杂性。

始终牢记通过解除引用访问与直接访问不同

我们在这里看到了。 const限定符实际上正在做它应该做的事情,阻止我们通过解除引用机制来改变** ptr_ptr_b 。 当然,我们已经设法显然改变了只读值,但这只是因为我们要求较差的const

另一个例子来自sheu的答案

 const char c = 'A'; char* ptr; const char** const_ptr = &ptr; // <-- ILLEGAL, but what if this were legal? *const_ptr = &c; *ptr = 'B'; // <- you just assigned to "const char c" above. printf("%c \n", c); printf("%c \n", *ptr); 

当你说you just assigned to "const char c" above ,事实并非如此,那只是参考抽象失控。