Passar um ponteiro não const para uma função que espera um ponteiro const geralmente não gera nenhum aviso (faz sentido, a função promete ser "melhor" do que o chamador esperaria), mas um ponteiro para ponteiro não const para uma função esperar que um ponteiro a ponteiro const gere um aviso (com gcc -Wall
, 11.4) e estou lutando para pensar por que
#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;
}
dando
$ 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
Qualquer esclarecimento sobre o porquê?
A razão é dada no padrão C. O código a seguir é de C 2018 6.5.16.1 6. Os comentários são meus.
Dadas estas declarações:
Suponha que permitimos atribuir (por chamada de função ou atribuição direta) a
char **
a aconst char **
, como em:Então, como
*cpp
é aconst char *
, podemos atribuir a ele aconst char *
, como em:Como
cpp
aponta parap
,*cpp = &c
mudap
para apontar parac
. E*p
é nominalmente achar
, podemos atribuir um valor a issochar
:Isso muda
c
, que é definido comconst
. Portanto, isso não pode ser permitido. A atribuiçãocpp = &p
é proibida para que isso não ocorra.Espero que fique mais claro: