Como uma função pode retornar um struct sem usar malloc? [duplicado]

Oct 22 2020

Eu sou novo em C, apenas uma pergunta sobre como retornar uma estrutura. Eu ouço pessoas dizendo que não há problema em retornar uma estrutura. Por exemplo:

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;
} 

Minhas perguntas são:

foo_aestá na foopilha de, portanto, após o footérmino, a pilha será desfeita, o que significa foo_aque não existe realmente na mainpilha da função, o ponteiro main_aque maincontém é na verdade um ponteiro ilegal, então como isso vai funcionar?

Respostas

5 EricPostpischil Oct 22 2020 at 06:26

Uma maneira comum de implementar isso é que a rotina de chamada aloca algum espaço para a estrutura, normalmente na pilha, e passa à rotina chamada um ponteiro para esse espaço. Este parâmetro não é visto no código-fonte C - é parte da convenção de chamada de como as rotinas são chamadas na linguagem assembly. Em seguida, a rotina chamada simplesmente armazena o conteúdo da estrutura no espaço apontado.

Em outras palavras, o código é implementado em grande parte como se tivesse sido 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;
} 

Se a estrutura for pequena, ela pode ser retornada em um registro ou em alguns registros. Tanto a rotina chamada quanto a rotina de chamada estariam usando a mesma convenção de chamada, que teria regras sobre quais estruturas são retornadas em registradores e quais são retornadas por meio de um apontado fornecido pelo chamador.