2012-05-04 11 views
8

por favor tengan paciencia conmigo, i m de otro idioma y novato en C y el aprendizaje desde http://c.learncodethehardway.org/book/learn-c-the-hard-way.htmldefinir una función que devuelve el puntero estructura

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 la segunda función Person_create devuelve un puntero de la Persona estructura. No entiendo es (puede ser porque soy de otro idioma, Erlang, rubí), ¿por qué lo definen como

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

no

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

lo siento si esta pregunta es demasiado básica.

+0

Comprender la diferencia entre 'Persona *' y 'Persona'. 'Persona *' es un puntero al objeto, mientras que 'Persona' es el objeto mismo. Ambos son diferentes tipos, como por ejemplo 'int *' y 'int' difieren. – Mahesh

+1

entonces, 'struct Person * Person_create' es lo mismo que' struct Person * Person_create', y 'struct Person * Person_create'? '' 'posición no importa? – allenhwkim

+1

sí, el espacio en blanco alrededor de '*' no importa aquí. –

Respuesta

11

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

Es posible devolver una estructura completa, al igual que:

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 utiliza muy a menudo.

3

La función devuelve who, que es un struct Person * - un puntero a una estructura. La memoria para contener la estructura se asigna por malloc(), y la función devuelve un puntero a esa memoria.

Si la función fueron declarados para volver struct Person y no un puntero, entonces who podría también ser declarado como una estructura. A su regreso, la estructura se copiará y se devolverá a la persona que llama. Tenga en cuenta que la copia es menos eficiente que simplemente devolver un puntero a la memoria.

2

Las estructuras no son punteros (o referencias) por defecto en C/C++, como lo son, por ejemplo, en Java. Struct Person Function() por lo tanto, la estructura de retorno misma (por valor, hacer una copia) no es un puntero.

A menudo no desea crear copias de objetos (copias superficiales por defecto, o copias creadas usando constructores de copia) ya que esto puede llevar bastante tiempo.

1

Copiar toda la estructura y no solo el puntero es menos eficiente porque un puntero sizeof es generalmente mucho más pequeño que sizeof de una estructura completa. También, una estructura puede contener punteros a otros datos en la memoria, y copia ciega que podría ser peligrosa para los datos asignados dinámicamente (si un código que maneja una copia lo liberaría, la otra copia quedaría con un puntero no válido).

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

2

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

Cuando llama a una función en C agrega un registro en el call stack. En la parte inferior de la pila de llamadas está la función main del programa que está ejecutando, en la parte superior se encuentra la función que se está ejecutando actualmente. Los registros en la pila 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 tiene acceso su programa: la memoria del montón. Aquí es donde asigna espacio usando malloc, y no está conectado a la pila de llamadas.

Cuando regresa de una función, la pila de llamadas se abre y se pierde toda la información asociada a la llamada a la función. Si desea devolver una estructura, tiene dos opciones: copiar los datos dentro de la estructura antes de que se saque de la pila de llamadas, o mantener los datos en la memoria de pila y devolver un puntero a la misma. Es más caro copiar el byte de datos para byte que simplemente devolver un puntero, y por lo tanto, normalmente querría hacerlo para ahorrar recursos (tanto en la memoria como en los ciclos de la CPU). Sin embargo, no viene sin costo; Cuando guarde sus datos en la memoria del montón, debe recordarlo al free cuando deje de usarlo, de lo contrario, su programa perderá memoria.

Cuestiones relacionadas