2016-03-19 6 views
0

サンプル:関数が構造体を返すとき、スタックまたはヒープに保持されますか?

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

typedef struct Animal{ 

    char name[100]; 
    char color[100]; 

} Animal; 

Animal Animal_new() { 

    Animal aux; 
    return aux; 
} 

int main() { 

    Animal a = Animal_new();  

} 

内部構造体を返すスタック
に作成され、ヒープに移動されるコピーですか?
返される構造体はフリーでなければなりませんか?

+1

オブジェクトがコピーされます。「ヒープに移動」はありません。 – user2864740

+2

特定のメモリ割り当て方式を使用して実装する必要はありません。それはあなたのプラットフォームに依存します - ABI。最も近代的。必要に応じて複合型を渡すためにレジスタを使用します。 – Olaf

答えて

1

呼び出し側関数は、呼び出し側が構造体を返すためにスタック上に割り当てた領域です。

基本的に、mainは構造体Animalを受け取ることを知っているので、自動的にスタックにスペースを作成し、これを新しく作成したものにポインタ(これはあなたから隠されていますがアセンブリレベルで発生します)を渡しますスタック領域をAnimal_New()関数に渡します。

この関数はスタックスペースに構造体の独自のコピーを持っています。返すとき、受け取ったポインタを介してその値を呼び出し元スタック空間にコピーします。

コメントに@MoLaiSkirulaisに頼ま:

Animal *heapAllocatedAnimal = malloc(sizeof(Animal)); 
memcpy(heapAllocatedAnimal,&a,sizeof(Animal)); 

@Olafによって参照しかしながら知るほとんどの実装を表すべきである。この「古典的な」実装は、疑わしい文書を読み取る際に想定よりも良好です。

+0

メインの「動物a」は「メインレベルのスタック」に保存されていますか?私はどのようにしてmallocを積み重ねることができますか?ベストプラクティスはありますか? memcpyを使う? – MoaLaiSkirulais

+1

ヒープにはどのようにmallocできますか?私はあなたの質問を理解していません。"a"変数のヒープコピーを作成する場合は、ヒープ内のAnimal構造体に十分な領域を割り当て、memcpyを使用して、aからmalloc関数によって返されたポインタにデータをコピーします。動物のようなもの* heapAllocatedAnimal = malloc(sizeof(Animal)); memcpy(heapAllocatedAnimal、&a、sizeof(Animal)); – DMH

+1

Cはオブジェクトの特定の割り当てを強制しません。 (古典的な)スタックを使用しない実装があります。それはABIによって定義されています。ほとんどの現代ABIは、例えば、レジスタ内のより小さな複合型。 – Olaf

3

構造体を返す関数は、呼び出し側のスコープ内の受信側の構造体へのポインタで、余分な隠し引数をとるようにコンパイラによって実装できます。この関数はローカルコピーをコピー先のコピーにコピーします。あなたのケースでは、両方とも自動ストレージに保存されます。

関数がヒープから返される構造体のメモリを割り当てていた場合は、structが(コピー先にコピーされた)値によって返され、そのアドレスが最終的には返されるため、失われた

構造が小さい場合、コンパイラはスカラー値の場合と同様にレジスタに戻すことを選択できます。

ABIは、これらの問題の処理方法を定義しています。 ABIはシステム特有のものであり、ハードウェアの能力や実装者の選択によって複雑さが増します。

1

structは値によって返されます。実際には、ヒープに到達するための唯一の方法は、malloc/calloc/reallocと呼ぶことです。

ローカル変数のAnimalは自動メモリに格納されます。値がmainに戻されると、auxAnimal_newからaまでmainのコピーが作成されます。しかし、コンパイラは、コピーを防止する方法で物を最適化することができますが、これが真だとは思わないかもしれません。