usar resueltos memoria manejo ejercicios dinamicos dinamica como arreglos c arrays malloc calloc

resueltos - malloc sizeof



Estoy muy confundido acerca de malloc() y calloc() en C (5)

2 - Esta declaración de matriz es estática:

pthread_t tid[MAX_OPS];

No necesitamos asignar bloque de memoria, en lugar de asignación dinámica:

pthread_t *tid = (pthread_t *)malloc( MAX_OPS * sizeof(pthread_t) );

No te olvides de liberar la memoria:

free(tid);

3 - La diferencia entre malloc y calloc es que calloc asigna un bloque de memoria para una matriz e inicializa todos sus bits en 0.

Siempre he programado en Java, y probablemente por eso estoy tan confundido acerca de esto:

En Java declaro un puntero:

int[] array

Inicializarlo o asignarle un poco de memoria:

int[] array = {0,1,0} int[] array = new int[3]

Ahora, en C, todo es tan confuso. Al principio pensé que era tan fácil como declararlo:

int array[]

e inicializándolo o asignándole algo de memoria:

int array[] = {0,1,0} int array[] = malloc(3*sizeof(int)) int array[] = calloc(3,sizeof(int))

A menos que esté equivocado, todo lo anterior es equivalente a Java-C, ¿verdad?

Entonces, hoy conocí un código en el que encontré lo siguiente:

pthread_t tid[MAX_OPS];

Y algunas líneas abajo, sin ningún tipo de inicialización ...

pthread_create(&tid[0],NULL,mou_usuari,(void *) 0);

Sorprendentemente (al menos para mí), el código funciona! Al menos en Java, eso devolvería una buena "NullPointerException"!

Entonces, en orden:

  1. ¿Estoy en lo cierto con todas las "traducciones" de Java-C?

  2. ¿Por qué funciona ese código?

  3. ¿Hay alguna diferencia entre usar malloc(n*sizeof(int)) y calloc(n,sizeof(int)) ?

Gracias por adelantado


C ofrece asignación de memoria estática además de dinámica: puede asignar arreglos fuera de la pila o en la memoria ejecutable (administrada por el compilador). Esto es lo mismo que en Java, puede asignar un int en la pila o un entero en el montón. Las matrices en C son como cualquier otra variable de pila: se salen del alcance, etc. En C99 también pueden tener un tamaño variable, aunque no se pueden redimensionar.

La principal diferencia entre {} y malloc / calloc es que las matrices {} están asignadas estáticamente (no es necesario liberarlas) y se inicializan automáticamente para usted, mientras que las matrices malloc / calloc deben liberarse explícitamente y usted debe inicializarlas explícitamente. Pero, por supuesto, los arreglos malloc / calloc no quedan fuera del alcance y usted puede (a veces) reasignarlos ().


Me resulta útil cuando está programando en C (a diferencia de C ++) para indicar explícitamente la matriz, para recordar que hay un puntero que se puede mover. Entonces, me gustaría comenzar por reformular su ejemplo como:

int array[] = {0,1,2}; int *array = malloc(3*sizeof(int)); int *array = calloc(3,sizeof(int));

El primero deja en claro que hay algo llamado matriz que apunta a un bloque de memoria que contiene una matriz 0, 1 y 2. no se puede mover a ningún otro lugar.

Su siguiente código: pthread_t tid [MAX_OPS];

De hecho, hace que se asigne una matriz con sizeof (pthread_t) * MAX_OPS. Pero no asigna un puntero llamado * tid. Hay una dirección de la base de la matriz, pero no puede moverla a otra parte.

El tipo ptherad_t es en realidad una cubierta para un puntero. Así que tid anterior es en realidad una serie de punteros. Y todos están asignados estáticamente, pero no están inicializados.

pthread_create toma la ubicación al principio de la matriz ( &tid[0] ), que es un puntero, y asigna un bloque de memoria para contener la estructura de datos pthread. El puntero está configurado para apuntar a la nueva estructura de datos y la estructura de datos está asignada.

Su última pregunta: la diferencia entre malloc(n*sizeof(int)) y calloc(n,sizeof(int)) es que la última inicializa cada byte a 0 , mientras que la primera no lo hace.


No puedes asignar memoria a una matriz. Una matriz tiene un tamaño fijo, durante toda su vida útil. Una matriz nunca puede ser nula. Una matriz no es un puntero.

malloc devuelve la dirección a un bloque de memoria que está reservado para el programa. No puede "asignar" eso (que es el bloque de memoria) a una matriz, pero puede almacenar la dirección de este bloque de memoria en un puntero: afortunadamente, la suscripción a la matriz se define a través de los punteros, por lo que puede "usar punteros como matrices" , p.ej

int *ptr = malloc(5 * sizeof *ptr); ptr[2] = 5; // access the third element "of ptr" free(ptr); // always free at the end

Cuando declara una matriz sin un tamaño (es decir, array[] ), simplemente significa que el tamaño de la matriz se determina a partir de la lista de inicializadores. Es decir

int array[] = {1, 2, 3, 4, 5}; // is equal to int array[5] = {1, 2, 3, 4, 5};

Intentar declarar una matriz sin un tamaño y sin un inicializador es un error.

El código pthread_t tid[MAX_OPS]; declara una matriz llamada tid de tipo pthread_t y de tamaño MAX_OPS .

Si la matriz tiene almacenamiento automático (es decir, la declaración está dentro de una función y no estática, no es global), entonces cada uno de los elementos de la matriz tiene un valor indeterminado (y causaría un comportamiento indefinido al intentar leer dicho valor). Afortunadamente, todo lo que hace la llamada a la función es que toma la dirección del primer elemento de la matriz como primer parámetro, y probablemente la inicialice (el elemento) dentro de la función.

La diferencia entre calloc y malloc es que el bloque de memoria que devuelve calloc se inicializa a cero. Es decir;

int *ptr = calloc(5, sizeof *ptr); // is somewhat equal to int *ptr = malloc(5 * sizeof *ptr); memset(ptr, 0, 5 * sizeof *ptr);

La diferencia entre

int *ptr = malloc(5 * sizeof *ptr); // and int array[5];

es que la array tiene almacenamiento automático, (se almacena en la pila), y se "libera" después de que está fuera de alcance. ptr , sin embargo, (se almacena en el montón), se asigna dinámicamente y debe ser free d por el programador.


Te faltan tres temas muy básicos y estrictos (¡y engañosos!) C:

  • La diferencia entre array y punteros.
  • La diferencia entre asignación estática y dinámica.
  • La diferencia de declarar variables en la pila o en el montón

Si escribe int array[] = malloc(3*sizeof(int)); obtendría un error de compilación (algo así como ''identificador'': la inicialización de la matriz necesita llaves ).

Esto significa que declarar una matriz solo permite la inicialización estática:

  • int array[] = {1,2,3}; que reserva 3 enteros contiguos en la pila;
  • int array[3] = {1,2,3}; que es lo mismo que el anterior;
  • int array[3]; que aún reserva 3 enteros contiguos en la pila, pero no los inicializa (el contenido será basura aleatoria)
  • int array[4] = {1,2,3}; cuando la lista de inicializadores no inicializa todos los elementos, el resto se establece en 0 (C99 §6.7.8 / 19): en este caso obtendrá 1,2,3,0

Tenga en cuenta que en todos estos casos no está asignando nueva memoria, simplemente está utilizando la memoria ya asignada a la pila. Se ejecutaría en un problema solo si la pila está llena (supongo que sería un desbordamiento de pila ). Por esta razón declarando int array[]; Sería incorrecto y sin sentido.

Para usar malloc tienes que declarar un puntero: int* array .

Cuando escribe int* array = malloc(3*sizeof(int)); En realidad estás haciendo tres operaciones:

  1. int* array le dice al compilador que reserve un puntero en la pila (una variable entera que contiene una dirección de memoria)
  2. malloc(3*sizeof(int)) asigna en el montón 3 enteros contiguos y devuelve la dirección del primero
  3. = asigna copias de ese valor de retorno (la dirección del primer entero que ha asignado) a su variable de puntero

Por lo tanto, para volver a su pregunta:

pthread_t tid[MAX_OPS];

es una matriz en la pila, por lo que no necesita ser asignada (si MAX_OPS es, por ejemplo, 16, en la pila se reservará el número de bytes contiguos necesarios para encajar 16 pthread_t). El contenido de esta memoria será basura (las variables de la pila no se inicializan a cero), pero pthread_create devuelve un valor en su primer parámetro (un puntero a una variable pthread_t ) y descarta cualquier contenido anterior, por lo que el código está bien.