ProgramaciónDesarrollador C

Hable detalladamente sobre el mecanismo de paso de arreglos a funciones en el lenguaje C. ¿Cuáles son los riesgos asociados con este modelo y cómo organizar correctamente un trabajo seguro con arreglos dentro de las funciones?

Supere entrevistas con el asistente de IA Hintsage

Respuesta

En el lenguaje C, los arreglos no se pasan a funciones por valor. Si se pasa un arreglo como argumento, en realidad se recibe un puntero al primer elemento del arreglo. Esto significa que la función modifica el arreglo original, no su copia.

Por ejemplo:

void fillArray(int arr[], int n) { for (int i = 0; i < n; ++i) arr[i] = i*i; } int main() { int myarr[5]; fillArray(myarr, 5); // ok }

Dentro de la función:

  • no es posible conocer el tamaño del arreglo original mediante sizeof(arr); esto devolverá el tamaño del puntero, no del arreglo.
  • solo se puede trabajar con el trozo de memoria cuyo tamaño se ha pasado explícitamente.

Se puede trabajar de manera correcta y segura con arreglos de la siguiente manera:

  • siempre pase el tamaño del arreglo como un argumento separado;
  • use constantes o macros para el tamaño;
  • si necesita proteger el arreglo de cambios, pase const int *arr.

Pregunta con trampa

Pregunta: ¿Es posible conocer el tamaño del arreglo pasado como argumento dentro de la función mediante int arr[] usando sizeof(arr)?

Respuesta: ¡No, no es posible! sizeof(arr) dentro de la función devolverá el tamaño del puntero al tipo (por ejemplo, 4 u 8 bytes), no el tamaño del arreglo.

Ejemplo:

void f(int arr[]) { printf("%zu\n", sizeof(arr)); // tamaño del puntero, ¡no del arreglo! } int main() { int x[10]; f(x); // Generalmente imprimirá 8 (x86_64) o 4 (x86) }

Ejemplos de errores reales


Historia

En un proyecto industrial, las funciones de copiado de arreglos intentaron calcular la longitud del arreglo sobre la marcha, usando sizeof(arr)/sizeof(int) dentro de la función. En la práctica, esto llevaba a copiar solo parte del arreglo, ya que el tamaño siempre era 1 (8/8), y los datos se sobrescribían de manera impredecible.


Historia

En una aplicación de red, la función de envío de datos aceptaba un búfer como un arreglo sin especificar explícitamente su tamaño, lo que provocaba que el búfer completo no se enviara a tiempo, o que se leyeran datos basura fuera de los límites del arreglo, lo que causaba errores en la transmisión y una inestabilidad en la conexión.


Historia

Al escribir una biblioteca para trabajar con imágenes, el programador no dotó a la función de coloración de arreglos de imágenes de un parámetro obligatorio para el tamaño. Esto condujo a un desbordamiento de búfer y a la caída del programa en ciertas entradas, lo cual solo fue descubierto en una prueba de integración con una imagen grande.