Lo que dices en tu publicación es absolutamente correcto. Yo diría que cada desarrollador C llega exactamente al mismo descubrimiento y exactamente a la misma conclusión cuando (si) alcanzan cierto nivel de competencia con el lenguaje C.
Cuando los detalles de su área de aplicación requieren una matriz de tamaño fijo específico (el tamaño de matriz es una constante de tiempo de compilación), la única forma correcta de pasar dicha matriz a una función es mediante un puntero a parámetro de matriz
void foo(char (*p)[10]);
(en el lenguaje C++ esto se realiza también con referencias
void foo(char (&p)[10]);
).
Esto habilitará la verificación de tipo de nivel de idioma, lo que asegurará que la matriz de tamaño exactamente correcto se suministre como argumento. De hecho, en muchos casos, la gente utiliza esta técnica de manera implícita, sin darse cuenta, ocultando el tipo de matriz detrás de un nombre typedef
typedef int Vector3d[3];
void transform(Vector3d *vector);
/* equivalent to `void transform(int (*vector)[3])` */
...
Vector3d vec;
...
transform(&vec);
nota, además, de que el código anterior es invariante con relación a Vector3d
tipo de ser una matriz o una struct
. Puede cambiar la definición de Vector3d
en cualquier momento desde una matriz a struct
y viceversa, y no tendrá que cambiar la declaración de la función. En cualquier caso, las funciones recibirán un objeto agregado "por referencia" (hay excepciones a esto, pero dentro del contexto de esta discusión esto es cierto).
Sin embargo, no verá este método de paso de matriz utilizado explícitamente con demasiada frecuencia, simplemente porque mucha gente se confunde por una sintaxis complicada y simplemente no son lo suficientemente cómodos con tales características del lenguaje C para usarlos correctamente. Por esta razón, en la vida real promedio, pasar una matriz como un puntero a su primer elemento es un enfoque más popular. Simplemente parece "más simple".
Pero, en realidad, utilizando el puntero al primer elemento de matriz que pasa es una técnica muy de nicho, un truco, que sirve a un propósito muy específico: su único propósito es facilitar pasar matrices de diferente tamaño (es decirtamaño de tiempo de ejecución). Si realmente necesita para ser capaz de procesar matrices de tamaño en tiempo de ejecución, a continuación, la forma correcta de pasar una matriz de este tipo es mediante un puntero a su primer elemento con el tamaño concreto suministrado por un parámetro adicional
void foo(char p[], unsigned plen);
realidad En muchos casos, es muy útil poder procesar matrices de tamaño de tiempo de ejecución, lo que también contribuye a la popularidad del método. Muchos desarrolladores C simplemente nunca encuentran (o nunca reconocen) la necesidad de procesar una matriz de tamaño fijo, por lo que permanecen ajenos a la técnica de tamaño fijo adecuada.
Sin embargo, si el tamaño de la matriz es fija, pasándola como un puntero a un elemento
void foo(char p[])
es un error importante a nivel de la técnica, que desafortunadamente es bastante generalizado en estos días. Una técnica de puntero a matriz es un enfoque mucho mejor en tales casos.
Otra razón que puede dificultar la adopción de la técnica de paso de matriz de tamaño fijo es el dominio del enfoque ingenuo para el tipado de matrices asignadas dinámicamente. Por ejemplo, si el programa prevé matrices fijas de tipo char[10]
(como en el ejemplo), un desarrollador promedio malloc
matrices tales como
char *p = malloc(10 * sizeof *p);
Esta matriz no se puede pasar a una función declarada como
void foo(char (*p)[10]);
que confunde al desarrollador promedio y les hace abandonar la declaración de parámetro de tamaño fijo sin darle más vueltas. En realidad, sin embargo, la raíz del problema radica en el ingenuo enfoque malloc
. El formato malloc
que se muestra arriba debe reservarse para matrices de tamaño de tiempo de ejecución. Si el tipo de matriz tiene tiempo de compilación tamaño, una mejor manera de malloc
se vería de la siguiente manera
char (*p)[10] = malloc(sizeof *p);
Esto, por supuesto, se puede pasar fácilmente de lo anterior declarada foo
foo(p);
y la el compilador realizará la comprobación de tipo correcta. Pero, de nuevo, esto es demasiado confuso para un desarrollador de C no preparado, por lo que no lo verá con demasiada frecuencia en el código diario promedio "típico".
nota: Desde C99 la matriz no tiene que ser de tamaño fijo como sugiere el título, '10' puede ser sustituido por cualquier variable en su alcance –