definir una función que devuelve el puntero de la estructura

Por favor, tenga paciencia conmigo, soy de otro idioma y soy novato en c y aprendílo en http://c.learncodethehardway.org/book/learn-c-the-hard-way.html

struct Person { char *name; int age; int height; int weight; }; struct Person *Person_create(char *name, int age, int height, int weight) { struct Person *who = malloc(sizeof(struct Person)); assert(who != NULL); who->name = strdup(name); who->age = age; who->height = height; who->weight = weight; return who; } 

Entiendo que la segunda función Person_create devuelve un puntero de estructura Person. No entiendo es (puede ser porque soy de otro idioma, erlang, ruby), ¿por qué lo define como

 struct Person *Person_create(char *name, int age, int height, int weight) 

no

 struct Person Person_create(char *name, int age, int height, int weight) 

y ¿hay otra manera de definir una función para devolver una estructura?

Lo siento si esta pregunta es demasiado básica.

Se define así porque devuelve un puntero a una estructura, no a una estructura. Usted asigna el valor de retorno a una struct Person * , no a la struct Person .

Es posible devolver una estructura completa, así:

 struct Person Person_create(char *name, int age, int height, int weight) { struct Person who; who.name = strdup(name); who.age = age; who.height = height; who.weight = weight; return who; } 

Pero no se usa muy a menudo.

La función devuelve who , que es una struct Person * : un puntero a una estructura. La memoria para mantener la estructura es asignada por malloc() , y la función devuelve un puntero a esa memoria.

Si se declara que la función devuelve struct Person y no un puntero, entonces también se podría declarar como estructura. Al regresar, la estructura sería copiada y devuelta a la persona que llama. Tenga en cuenta que la copia es menos eficiente que simplemente devolver un puntero a la memoria.

La función Person_create devuelve un puntero a una struct Person por lo que debe definir el valor de retorno para que sea un puntero (agregando el *). Para comprender la razón por la que se devuelve un puntero a una estructura y no a la estructura en sí, se debe entender la forma en que C maneja la memoria.

Cuando llama a una función en C, agrega un registro para ella en la stack de llamadas . En la parte inferior de la stack de llamadas está la función main del progtwig que está ejecutando, en la parte superior está la función que se está ejecutando actualmente. Los registros en la stack contienen información tal como los valores de los parámetros pasados ​​a las funciones y todas las variables locales de las funciones.

Hay otro tipo de memoria a la que su progtwig tiene acceso: memoria de stack. Aquí es donde se asigna el espacio usando malloc , y no está conectado a la stack de llamadas.

Cuando regresa de una función, la stack de llamadas aparece y toda la información asociada con la llamada de función se pierde. Si desea devolver una estructura, tiene dos opciones: copiar los datos dentro de la estructura antes de que salga de la stack de llamadas, o mantener los datos en la memoria del montón y devolverle un puntero. Es más caro copiar el byte de datos por byte que simplemente devolver un puntero y, por lo tanto, normalmente querría hacer eso para ahorrar recursos (tanto la memoria como los ciclos de la CPU). Sin embargo, no viene sin costo; cuando mantenga sus datos en la memoria del montón, debe recordar free cuando deje de usarlos, de lo contrario, su progtwig perderá memoria.

Las estructuras no son punteros (o referencias) de forma predeterminada en C / C ++, como son, por ejemplo, en Java. Struct Person Function () por lo tanto, devolvería la estructura en sí misma (por valor, haciendo una copia) no como un puntero.

A menudo, no desea crear copias de objetos (copias poco profundas de forma predeterminada o copias creadas utilizando constructores de copia), ya que esto puede llevar bastante tiempo en breve.

Copiar toda la estructura y no solo el puntero es menos eficiente porque el tamaño de un puntero suele ser mucho más pequeño que el tamaño de una estructura en sí.

Además, una estructura puede contener punteros a otros datos en la memoria, y la copia a ciegas puede ser peligrosa para los datos asignados dinámicamente (si un código que maneja una copia la libere, la otra copia quedará con un puntero no válido).

Por lo tanto, una copia superficial es casi siempre una mala idea, a menos que esté seguro de que el original está fuera del scope, y entonces, ¿por qué no devolvería un puntero a la estructura (una estructura asignada dinámicamente en el montón, por supuesto)? no se destruirá como se destruyen las entidades asignadas a la stack, al regresar de una función).