2012-10-01 14 views
24

estoy aprendiendo cómo crear matrices 1D dinámicos en C. El código siguiente intenta hacer esto:Dynamic Array in C - ¿Es correcto mi entendimiento de malloc/realloc?

  1. crear una matriz dinámica de longitud 10, que contiene dobles, utilizando malloc.
  2. Establezca cada entrada de la matriz en j/100 para j = 0,1, ..., 9. A continuación, imprima .
  3. Agregue una entrada vacía adicional al final de la matriz con realloc.
  4. Establezca la nueva entrada en j/100 e imprima de nuevo cada entrada.

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 este derecho?

2) Tutoriales que encontré usar malloc sin poner el (double*) en frente. P.ej.

int *pointer; 

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

Esto no compila para mí en Visual Studio 2010, Windows 7. El error es "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 para adivinar que es porque los compiladores que están utilizando completan automáticamente el (int*) para ellos en mi ejemplo?

+0

"value of type void no se puede asignar a la entidad de tipo int" no es un error que debe producir un compilador * C *. El problema es que estás usando un compilador * C++ *. Asegúrese de que su archivo fuente se llame ' .c'. –

Respuesta

31

Estás cerca.

En C (al menos desde la versión 1989 de la norma), el reparto antes de malloc y realloc es innecesario, ya que C se puede convertir valores de tipo void *-int * sin un yeso. Esto es no verdadero para C++, por lo que según el error que está obteniendo, parece que está compilando este código como C++ y no C. Consulte la documentación de VS2010 para determinar cómo compilar el código como C.

la siguiente es mi estilo preferido para escribir una llamada malloc:

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

Dado 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 cambia el tipo de data.

En cuanto a la llamada realloc, es más seguro asignar el resultado a un valor de puntero temporal. realloc devolverá NULL si no se puede ampliar la memoria intermedia, por lo que es más seguro para 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 apoyo de Microsoft para C termina con la versión 1989 de la lengua; Desde entonces, se han llevado a cabo dos revisiones del estándar de idioma, que han introducido algunas características nuevas y obsoletos. Por lo tanto, aunque algunos compiladores C admiten características C99 como declaraciones mixtas y código, matrices de longitud variable, etc., VS2010 no lo hará.

+0

Gracias, eso fue muy útil. – Legendre

+0

Actualización: VS2015 admite C99 + C11 parcial y opción para objetivos de WinXP. Por lo tanto, Microsoft continuó con el soporte ISO C en 2015. –

4

En C, no debe emitir el valor de retorno de malloc().

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

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

Esto compila. Pero Visual Studio 2010 advierte que "value of type void no se puede usar para inicializar una entidad de tipo double". ¿Está bien simplemente ignorar la advertencia? – Legendre

10

1) ¿Estoy codificación de este derecho?

Mayormente. 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 de retorno de realloc y comprobar si es NULL (y también debe comprobar el valor de retorno de malloc).

2) Tutoriales que encontré usar malloc sin poner el (doble *) al frente.

En C, malloc devuelve un void* que implícitamente se puede convertir en cualquier otro tipo de puntero, por lo que no se necesita ningún molde (y ampliamente desaniman porque colada que puede ocultar errores). Visual Studio aparentemente compila el código como C++ donde se requiere el elenco.

+0

+1 gracias por la ayuda. – Legendre