por - Pase una matriz bidimensional a una función de parámetro constante
pasar un arreglo como parametro en java (2)
Aprendí de
C Primer Plus
que si desea proteger una matriz de ser modificada accidentalmente por una función, debe agregar un modificador
const
antes de la declaración del puntero en el encabezado de la definición de la función.
Siguiendo este consejo sensato, en el siguiente ejemplo mínimo, estoy tratando de pasar una matriz de
array
bidimensional no constante a la función
Sum2D
,
Sum2D
parámetro es un
pointer-to-const-int[2]
.
#include <stdio.h>
#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;
}
Sin embargo,
gcc
no puede compilar con éxito este código sin emitir las siguientes advertencias:
$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 qué la advertencia?
2) ¿Cómo puedo eliminar el "ruido"? (Además de agregar
const
a la declaración de
array
).
(Si la
array
y la función utilizan una matriz unidimensional, no hay advertencia).
Información del sistema:
Ubuntu 14.04LTS
Compilador: gcc 4.8.2
Este es un desafortunado "error" en el diseño de C;
T (*p)[N]
no se convierte implícitamente en
T const (*p)[N]
.
Tendrá que usar un reparto feo o hacer que el parámetro de la función no acepte
const
.
A primera vista parece que esta conversión debería ser legal. C11 6.3.2.3/2:
Para cualquier calificador q , un puntero a un tipo no calificado con q puede convertirse en un puntero a la versión q calificada del tipo;
Sin embargo, también mire C11 6.7.3 / 9 (was / 8 en C99):
Si la especificación de un tipo de matriz incluye cualquier calificador de tipo, el tipo de elemento es así calificado, no el tipo de matriz.
Esta última cita dice que
int const[4]
no se
considera una versión calificada
const
de
int[4]
.
En realidad es una matriz no calificada de 4
const int
s.
int[4]
e
int const[4]
son matrices de diferentes tipos de elementos.
Por lo tanto, 6.3.2.3/2 no permite que
int (*)[4]
se convierta en
int const (*)[4]
.
Otra situación extraña en la que aparece este problema con
const
y arrays es cuando se usan typedefs;
por ejemplo:
typedef int X[5];
void func1( X const x );
void func1( int const x[5] );
Esto provocaría un error del compilador:
X const x
significa que
x
es const, pero apunta a una matriz de
int
s no const;
mientras que
int const x[5]
significa que
x
no es constante sino que apunta a una serie de constantes.
Más información here , gracias a @JensGustedt
Puede escribir cast the array mientras llama a la función. No convertirá automáticamente no const en const. Puedes usar esto.
Sum2D( (const int (*)[])array, ROWS );