Matriz dinámica en C - ¿Mi comprensión de malloc y realloc es correcta?


Estoy aprendiendo a crear arrays dinámicos 1D en C. El siguiente código intenta hacer lo siguiente:

  1. Usando malloc, cree un array dinámico de length 10, que contenga valores de tipo double.
  2. Establece cada entrada de la matriz en j/100 para j = 0, 1,..., 9. Entonces imprímelo.
  3. Agregue una entrada vacía adicional al final de la matriz usando realloc.
  4. Establezca la nueva entrada en j/100 e imprima cada entrada nuevo.

Pruebas:

 double* data = (double*)malloc(10*sizeof(double));

 for (j=0;j<10;j++)
 {
      data[j]= ((double)j)/100;
      printf("%g, ",data[j]);
 }

 printf("\n");

 data = (double*)realloc(data,11*sizeof(double));

 for (j=0;j<11;j++)
 {
     if (j == 10){ data[j]= ((double)j)/100; }
     printf("%g, ",data[j]);
 }

 free((void*) data);

Preguntas

  1. ¿Estoy codificando esto bien?

  2. Tutoriales Encontré usar malloc sin poner el (double*) delante. Por ejemplo,

    Int * pointer;
    pointer = malloc(2 * sizeof (int));

Esto no compila para mí en Visual Studio 2010, Windows 7. El mensaje de error es

El valor de tipo void no se puede asignar a la entidad de tipo int.

¿Por qué funciona para esos tutoriales y no para mí? ¿Tengo razón al suponer que es porque los compiladores que están usando rellenan automáticamente el (int*) para ellos en mi ejemplo?

Author: Nemo, 2012-10-01

3 answers

Estás cerca.

En C (al menos desde la versión de 1989 del estándar), el molde antes de malloc y realloc es innecesario, ya que C puede convertir valores de tipo void * a int * sin un molde. Esto es no verdadero para C++, así que basado en el error que está obteniendo, suena como si estuviera compilando este código como C++ y no C. Consulte la documentación de VS2010 para determinar cómo compilar código como C.

El siguiente es mi estilo preferido para escribir un malloc llamada:

double *data = malloc(10 * sizeof *data);

Ya que el tipo de la expresión *data es double, sizeof *data es equivalente a sizeof (double). Esto también significa que no tiene que ajustar sus llamadas malloc si el tipo de data cambia.

En cuanto a la llamada realloc, es más seguro asignar el resultado a un valor de puntero temporal. realloc devolverá NULL si no puede extender el búfer, por lo que es más seguro escribir

double *tmp;
...
tmp = realloc(data, 11 * sizeof *data);
if (!tmp)
{
  // could not resize data; handle as appropriate
}
else
{
  data = tmp;
  // process extended buffer
}

Tenga en cuenta que el soporte de Microsoft para C termina con la versión de 1989 del lenguaje; ha habido dos revisiones del estándar de lenguaje desde entonces, que han introducido algunas características nuevas y obsoletas. Así, mientras que algunos compiladores de C soportan características de C99 como declaraciones mixtas y código, matrices de longitud variable, etc., VS2010 no lo hará.

 34
Author: John Bode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-01 15:18:18

1) ¿Estoy codificando bien esto?

En su mayoría. Pero data = (double*)realloc(data,11*sizeof(double)); pierde la referencia a la memoria asignada si realloc falla, debe usar un puntero temporal para mantener el valor devuelto de realloc y verificar si es NULL (y también debe verificar el valor devuelto de malloc).

2) Tutoriales He encontrado uso malloc sin poner el (doble*) en frente.

En C, malloc devuelve un void* que se puede convertir implícitamente a cualquier otro tipo de puntero, por lo que no cast es necesario (y ampliamente desaconsejado porque casting que puede ocultar errores). Visual Studio aparentemente compila el código como C++ donde se requiere el cast.

 12
Author: Daniel Fischer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-01 15:11:18

En C, no debe lanzar el valor devuelto de malloc().

Además, es una mala idea codificar el tipo en el argumento malloc(). Esta es una mejor manera:

double* data = malloc(10 * sizeof *data);
 5
Author: unwind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-01 15:09:25