Passing a non-const pointer to a function which expects a const pointer usually raises no warning (makes sense, the function promises to be "nicer" than the caller would expect), but a non-const pointer-to-pointer to a function expecting an const pointer-to-pointer does raise a warning (with gcc -Wall
, 11.4) and I’m struggling to think why
#include <stdio.h>
int foo(const int *i)
{
return *i;
}
int bar(const int **i)
{
return **i;
}
int main(void)
{
int i = 3, *pi = &i, **ppi = π
printf("foo: %i\n", foo(pi));
printf("bar: %i\n", bar(ppi));
return 0;
}
giving
$ gcc -Wall -o const const.c
const.c: In function ‘main’:
const.c:18:27: warning: passing argument 1 of ‘bar’ from incompatible pointer type [-Wincompatible-pointer-types]
18 | printf("bar: %i\n", bar(ppi));
| ^~~
| |
| int **
const.c:8:21: note: expected ‘const int **’ but argument is of type ‘int **’
8 | int bar(const int **i)
| ~~~~~~~~~~~~^
$ ./const
foo: 3
bar: 3
Any enlightenment as to why?
>Solution :
The reason is given in the C standard. The following code is from C 2018 6.5.16.1 6. The comments are mine.
Given these declarations:
const char **cpp;
char *p;
const char c = ’A’;
Suppose we allowed assigning (by function call or direct assignment) a char **
to a const char **
, as in:
cpp = &p;
Then, since *cpp
is a const char *
, we can assign it a const char *
, as in:
*cpp = &c;
Since cpp
points to p
, *cpp = &c
changes p
to point to c
. And *p
is nominally a char
, we can assign a value to that char
:
*p = 0;
That changes c
, which is defined with const
. So this cannot be allowed. The assignment cpp = &p
is prohibited so this does not occur.