Incompatible const pointers

Advertisements

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 = &pi;

  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.

Leave a ReplyCancel reply