¿Cómo puede una función devolver una estructura sin usar malloc? [duplicar]

Oct 22 2020

Soy nuevo en C, solo una pregunta sobre cómo devolver una estructura. Escucho a la gente decir que está bien devolver una estructura. Por ejemplo:

struct MyObj{
   int x,y,z;
};

struct MyObj foo(){
    struct MyObj foo_a;
    foo_a.x = 10;
    foo_a.y = 10;
    foo_a.z = 10;

    return foo_a;
}        

int main () {
    struct MyObj main_a = foo();
    return 0;
} 

Mis preguntas son:

foo_aestá en foola pila, así que después del foofinal, la pila se desenrollará, lo que significa foo_aque en realidad no existe en mainla pila de la función, el puntero main_aque maincontiene es en realidad un puntero ilegal, entonces, ¿cómo va a funcionar?

Respuestas

5 EricPostpischil Oct 22 2020 at 06:26

Una forma común de implementar esto es que la rutina de llamada asigna algo de espacio para la estructura, generalmente en la pila, y pasa a la rutina llamada un puntero a ese espacio. Este parámetro no se ve en el código fuente de C; es parte de la convención de llamadas de cómo se llaman las rutinas en lenguaje ensamblador. Luego, la rutina llamada simplemente almacena el contenido de la estructura en el espacio apuntado.

En otras palabras, el código se implementa en gran medida como si se hubiera escrito:

void foo(struct MyObj *temporary){
    struct MyObj foo_a;
    foo_a.x = 10;
    foo_a.y = 10;
    foo_a.z = 10;
    *temporary = foo_a;
}        

int main () {
    struct MyObj temporary;
    foo(&temporary);
    struct MyObj main_a = temporary;
    return 0;
} 

Si la estructura es pequeña, podría devolverse en un registro o en algunos registros. Tanto la rutina llamada como la rutina de llamada utilizarían la misma convención de llamada, que tendría reglas sobre qué estructuras se devuelven en los registros y cuáles se devuelven a través de un apuntado proporcionado por el llamador.