Passar um array bidimensional para uma function de parâmetro constante

Eu aprendi com o C Primer Plus que, se você quer proteger um array de ser acidentalmente modificado por uma function, você deve adicionar o modificador de const antes da declaração do ponteiro no header da definição da function.

Seguindo este conselho sensato, no seguinte exemplo mínimo, eu estou tentando passar uma matriz de array bidimensional não constante para a function Sum2D , um parâmetro do qual é um pointer-to-const-int[2] .

 #include  #define ROWS 2 #define COLS 2 int Sum2D(const int ar[][COLS], int rows); //use `const` to protect input array int main(void) { int array[ROWS][COLS]={{1,2},{3,4}}; //the non-constant array printf( "%d\n", Sum2D(array,ROWS) ); return 0; } int Sum2D(const int ar[][COLS], int rows) { int total=0; int i,j; for( i=0 ; i<rows ; i++ ) { for( j=0 ; j<COLS ; j++ ) { total+=ar[i][j]; } } return total; } 

No entanto, o gcc não pode compilar com sucesso este código sem emitir os seguintes avisos:

 $gcc -ggdb3 -Wall -Wextra -o test test.c test.c: In function 'main': test.c:16:2: warning: passing argument 1 of 'Sum2D' from incompatible pointer type [enabled by default] printf( "%d\n", Sum2D(array,4) ); ^ test.c:4:5: note: expected 'const int (*)[4]' but argument is of type 'int (*)[4]' int Sum2D(const int ar[][COLS], int rows); ^ 

1) Por que o aviso?

2) Como posso eliminar o “ruído”? (Além de adicionar const à declaração do array .)

(Se a array e a function usarem uma matriz unidimensional, não haverá aviso.)

Informação do sistema:

Ubuntu 14.04LTS

Compilador: gcc 4.8.2

Este é um “bug” infeliz no design de C; T (*p)[N] não converte implicitamente para T const (*p)[N] . Você terá que usar um feitiço feio ou ter o parâmetro de function não aceito const .


À primeira vista, parece que esta conversão deve ser legal. C11 6.3.2.3/2:

Para qualquer qualificador q , um ponteiro para um tipo não- q- qualificado pode ser convertido em um ponteiro para a versão q- qualificada do tipo;

No entanto, olhe também para C11 6.7.3 / 9 (era / 8 em C99):

Se a especificação de um tipo de matriz include qualquer qualificador de tipo, o tipo de elemento será qualificado, não o tipo de matriz.

Esta última citação diz que int const[4] não é considerado uma versão qualificada de const de int[4] . Na verdade, é um array não const qualificado de 4 const int s. int[4] e int const[4] são matrizes de diferentes tipos de elementos.

Portanto, 6.3.2.3/2 não permite que int (*)[4] seja convertido para int const (*)[4] .


Outra situação estranha em que esse problema com const e arrays aparece é quando typedefs estão em uso; por exemplo:

 typedef int X[5]; void func1( X const x ); void func1( int const x[5] ); 

Isso causaria um erro do compilador: X const x significa que x é const, mas está apontando para uma matriz de não-const int s; enquanto int const x[5] significa que x não é const mas está apontando para um array de constantes!

Leia mais aqui , graças a @JensGustedt

Você pode digitar a matriz ao chamar a function. Não irá converter automaticamente não-const em const. Você pode usar isso.

 Sum2D( (const int (*)[])array, ROWS );