usar como array c arrays malloc

como - malloc sizeof



char x[256] vs. char*= malloc(256*sizeof(char)); (6)

Alguien aquí recientemente me señaló un código mío que estoy usando

char* name = malloc(256*sizeof(char)); // more code free(name);

Tenía la impresión de que esta forma de configurar una matriz era idéntica a usar

char name[256];

y que ambas formas requerirían el uso de free (). ¿Estoy equivocado y, si es así, alguien podría explicar en términos de bajo nivel cuál es la diferencia?


y que ambas formas requerirían el uso de free ().

No, solo el primero necesita el uso de un gratis. El segundo se asigna en la pila. Eso hace que sea increíblemente rápido de asignar. Mira aquí:

void doit() { /* ... */ /* SP += 10 * sizeof(int) */ int a[10]; /* ... (using a) */ } /* SP -= 10 */

Cuando lo crea, el compilador en tiempo de compilación conoce su tamaño y le asigna el tamaño correcto en la pila. La pila es una gran porción de memoria continua ubicada en algún lugar. Poner algo en la pila simplemente incrementará (o disminuirá dependiendo de tu plataforma) el stackpointer. Salir del alcance hará lo contrario, y su matriz se liberará. Eso sucederá automáticamente Por lo tanto, las variables creadas de esa manera tienen una duración de almacenamiento automática .

Usar malloc es diferente. Ordenará algún trozo de memoria grande arbitrario (desde un lugar llamado freestore ). El tiempo de ejecución deberá buscar un bloque de memoria razonablemente grande. El tamaño se puede determinar en tiempo de ejecución, por lo que el compilador generalmente no puede optimizarlo en tiempo de compilación. Como el puntero puede salir del alcance o copiarse, no existe un acoplamiento inherente entre la memoria asignada y el puntero al que se asigna la dirección de memoria, por lo que la memoria aún se asigna incluso si ya dejó la función hace mucho tiempo. . Tienes que llamar gratis para pasar la dirección que obtuviste de malloc manualmente si ha llegado el momento de hacerlo.

Alguna forma "reciente" de C, llamada C99, le permite dar a las matrices un tamaño de tiempo de ejecución. Es decir, a usted se le permite hacer:

void doit(int n) { int a[n]; // allocate n * sizeof(int) size on the stack */ }

Pero esa característica debería evitarse mejor si no tiene una razón para usarla. Una razón es que no es a prueba de fallas: si ya no hay memoria disponible, cualquier cosa puede suceder. Otra es que C99 no es muy portátil entre los compiladores.


En el primer código, la memoria se asigna dinámicamente en el montón. Esa memoria debe ser liberada con free (). Su vida útil es arbitraria: puede cruzar límites de funciones, etc.

En el segundo código, los 256 bytes se asignan en la pila, y se recuperan automáticamente cuando la función regresa (o al finalizar el programa si está fuera de todas las funciones). Entonces no tiene que (y no puede) llamar gratis () en él. No puede filtrarse, pero tampoco durará más allá del final de la función.

Elija entre los dos según los requisitos para la memoria.

Adición (Pax):

Si puedo agregar algo a esto, Ned, la mayoría de las implementaciones suelen proporcionar más pila que pila (al menos de forma predeterminada). Esto normalmente no importará en 256 bytes, a menos que ya te estés quedando sin pila o haciendo muchas cosas recursivas.

Además, sizeof (char) siempre es 1 de acuerdo con el estándar, por lo que no necesita esa multiplicación superflua. Aunque el compilador probablemente lo optimice, hace que el código sea feo.

End addéndum (Pax).


Esto es incorrecto: la declaración de matriz no requiere una forma gratuita. Además, si esto está dentro de una función, se asigna en la pila (si la memoria se sirve) y se libera automáticamente con la función devuelve - ¡no devuelva una referencia a la persona que llama!


Hay una tercera posibilidad aquí, que es que la matriz puede declararse externa a una función, pero estáticamente, por ejemplo,

// file foo.c char name[256]; int foo() { // do something here. }

Me sorprendieron bastante las respuestas a otra pregunta sobre SO que alguien sintió que esto era inapropiado en C; aquí ni siquiera se menciona, y estoy un poco confundido y sorprendido (como "¿qué están enseñando a los niños en la escuela estos días?") sobre esto.

Si utiliza esta definición, la memoria se asigna estáticamente, ni en el montón ni en la pila, sino en el espacio de datos de la imagen. Por lo tanto, ninguno de los dos debe ser administrado como con malloc / free, ni tiene que preocuparse por la reutilización de la dirección como lo haría con una definición automática.

Es útil recordar toda la cosa "declarada" vs "definida" aquí. Aquí hay un ejemplo

/* example.c */ char buf1[256] ; /* declared extern, defined in data space */ static char buf2[256] ; /* declared static, defined in data space */ char * buf3 ; /* declared extern, defined one ptr in data space */ int example(int c) { /* c declared here, defined on stack */ char buf4[256] ; /* declared here, defined on stack */ char * buf5 = malloc(256)] /* pointer declared here, defined on stack */ /* and buf4 is address of 256 bytes alloc''d on heap */ buf3 = malloc(256); /* now buf3 contains address of 256 more bytes on heap */ return 0; /* stack unwound; buf4 and buf5 lost. */ /* NOTICE buf4 memory on heap still allocated */ /* so this leaks 256 bytes of memory */ }

Ahora en un archivo completamente diferente

/* example2.c */ extern char buf1[]; /* gets the SAME chunk of memory as from example.c */ static char buf2[256]; /* DIFFERENT 256 char buffer than example.c */ extern char * buf3 ; /* Same pointer as from example.c */ void undoes() { free(buf3); /* this will work as long as example() called first */ return ; }


Analice su declaración

char* name = malloc(256*sizeof(char)); // one statement char *name; // Step 1 declare pointer to character name = malloc(256*sizeof(char)); // assign address to pointer of memory from heap name[2]; // access 3rd item in array *(name+2); // access 3rd item in array name++; // move name to item 1

Traducción: el nombre ahora es un puntero al carácter al que se le asigna la dirección de alguna memoria en el montón

char name[256]; // declare an array on the stack name++; // error name is a constant pointer *(name+2); // access 3rd item in array name[2]; // access 3rd item in array char *p = name; p[2]; // access 3rd item in array *(p+2); // access 3rd item in array p++; // move p to item 1 p[0]; // item 1 in array

Traducción: Nombre es un puntero constante a un personaje que apunta a un poco de memoria en la pila

En C las matrices y punteros son lo mismo más o menos. Las matrices son punteros constantes a la memoria. La principal diferencia es que cuando llamas a malloc, sacas tu memoria del montón y cualquier memoria que se tome del montón debe liberarse del montón. Cuando declaras la matriz con un tamaño, se le asigna memoria desde la pila. No puede liberar esta memoria porque se hace libre para liberar memoria del montón. La memoria en la pila se liberará automáticamente cuando la unidad de programa actual regrese. En el segundo ejemplo, free (p) también sería un error. p es un puntero al conjunto de nombres en la pila. Entonces al liberar p estás intentando liberar la memoria en la pila.

Esto no es diferente de:

int n = 10; int *p = &n;

liberar p en este caso sería un error porque p apunta a n, que es una variable en la pila. Por lo tanto, p contiene una ubicación de memoria en la pila y no se puede liberar.

int *p = (int *) malloc(sizeof(int)); *p = 10; free(p);

en este caso, el libre es correcto porque p apunta a una ubicación de memoria en el montón que fue asignada por malloc.


dependiendo de dónde esté ejecutando esto, el espacio de la pila puede ser enorme. Si, por ejemplo, está escribiendo código BREW para teléfonos Verizon / Alltel, generalmente está restringido a minúsculas, pero tiene un acceso cada vez mayor al montón.

Además, como char [] se utiliza con más frecuencia para cadenas de caracteres, no es una mala idea permitir que el método de construcción de cadenas asigne la memoria que necesita para la cadena en cuestión, en lugar de esperar que siempre y para siempre 256 (o el número que decreto) será suficiente.