regresando el puntero a una estructura en C

este progtwig devuelve un puntero a una estructura .
Cuando imprimo el contenido, el nombre no se muestra correctamente, mientras que las otras dos variables se imprimen correctamente.
¿Cual podría ser el problema? Aquí está el código en C

#include struct student { char name[20]; int marks; int rank; }; struct student stu; struct student *create(); void main() { struct student *ptr; ptr = create(); printf("%s\t %d\t %d\t",ptr->name,ptr->marks,ptr->rank); } struct student *create() { struct student stu = {"john",98,9}; struct student *ptrr; ptrr = &stu; return ptrr; } 

El problema aquí es que estás devolviendo un puntero a una variable local . Las variables locales quedan fuera del scope una vez que se definen la función en los retornos. Eso significa que el puntero que devuelva apuntará a la memoria no asignada después de que la función regrese. Usar ese puntero conducirá a un comportamiento indefinido .

Hay tres maneras de resolver esto:

  1. Utilice una variable global y devuelva un puntero a eso. La vida útil de una variable global es la vida útil del progtwig.
  2. Utilice una variable local static . También tendrá la vida igual al progtwig.
  3. Asigne la estructura dinámicamente cuando sea necesario y devuelva ese puntero.

Los puntos 1 y 2 tienen un problema porque solo se puede tener un único objeto. Si modifica ese objeto, todos los lugares donde tenga un puntero a ese único objeto verán esos cambios.

Punto 3 es la forma en que te recomiendo que vayas. El problema con eso es que una vez que haya terminado con el objeto, debe liberar la memoria que asigne.

Usted creó stu localmente en la stack en su función de creación. Cuando regresó de esa función, la stack se abrió, invalidando los datos a los que apunta el puntero.

Creas una variable local que vive en una función create() . Un puntero en esta variable es incorrecto fuera de la función create() .

Como respondió Joachim Pileborg , no debe devolver un puntero a una variable local. Por cierto, si comstack con un GCC reciente usando gcc -Wall -g (por ejemplo, habilitando casi todas las advertencias e información de depuración) debería recibir una advertencia.

Por lo tanto, en la práctica, debe decidir que su create devuelve un puntero de stack, y adoptar, luego obedecer la convención de que su interlocutor está liberando ese puntero.

  void main() { struct student *ptr; ptr = create(); printf("%s\t %d\t %d\t",ptr->name,ptr->marks,ptr->rank); free (ptr); } struct student *create() { struct student stu = {"john",98,9}; struct student *ptrr = malloc(sizeof struct student); if (!ptrr) { perror("malloc student"); exit(EXIT_FAILURE); } *ptrr = stu; return ptrr; } 

Lea atentamente las wikipages sobre asignación dinámica de memoria C , gestión de memoria manual , montón , memory leaks y página de manual malloc (3) . Si tiene la suerte de codificar en Linux, aprenda sobre valgrind .

PD. Siempre prueba el resultado de malloc (contra falla). Siempre inicialice la zona de memoria obtenida (tal vez borrándola con memset (3) ….).

Addenda: buenos hábitos.

Debe comstackr con todas las advertencias y la información de depuración. Si usa GCC , compile con gcc -Wall -g y mejore su código hasta que no tenga advertencias.

Definitivamente, debe aprender a usar el depurador (en Linux, gdb ) y poder paso a paso el progtwig y mostrar varias variables locales.

Addenda: utilizando Boehm GC

Para completar (especialmente en Linux), y solo una vez que te conviertas en un progtwigdor experto en C , puedes considerar usar el recolector de basura conservador de Boehm (ver este enlace ): entonces harías GC_malloc lugar de malloc y no necesitarás free explícitamente el zona de puntero. El coleccionista Boehm podría (quizás más tarde, especialmente en progtwigs más grandes) liberar mágicamente la memoria para usted. Pero aprender sobre la recolección de basura y el recuento de referencias (que puede verse como una forma deficiente de GC, ya que no administra bien las referencias circulares ) es útil. También puedes diseñar tu propio GC (tarea difícil), como hice en qish o MELT …