2017-02-17 4 views
2

構造体のメンバ変数を2つの異なる関数save_struct_model_1save_struct_model_2で出力しようとしています。両方とも正常に動作し、正しい値を出力するようです。これらのうちどれが正しいか、好ましいか。Cの構造ポインタ

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

struct model{ 
    char *name; 
    int year; 
}; 

void save_struct_model_1(struct model *s){ 
     printf("%s ", s->name); 
     printf("%d \n",s->year); 
} 

void save_struct_model_2(struct model s){ 
     printf("%s ", s.name); 
     printf("%d \n",s.year); 
} 

int main() 
{ 

typedef struct model M; 

M * honda = (M *) malloc (sizeof(M)); 
honda->name="civic"; 
honda->year=2000; 

save_struct_model_1(honda); 
save_struct_model_2(*honda);  

return 0; 
} 
+3

秒1つのコピー '* honda'からの一時的な値と、元の構造体を変更することはできません。 –

+0

ありがとう@BlagovestBuyukliev、 – marc

+3

ほとんどの場合、 'model_1'が好まれます。あなたが印刷しているだけの場合は、 'void save_struct_model_1(const struct model * s);を使ってください。' struct model {int x [1000000000]; }; '次に、4GB +をスタックにプッシュします。各コールでパフォーマンスのペナルティはもちろん、スタックを爆破します。そのため、structポインタを渡すのがその理由です。 35年以上のCを経て、モデル2を使用する機会は一度もありませんでした。 –

答えて

3

主に主観的です。しかし、私は構造体の値をコピーすることを避けるため、ポインタのバージョン(save_struct_model_1()を使用して)が良いと言うでしょう。

あなたのコードには目立った影響はないかもしれませんが、構造体が100個のメンバーを持ち、それらをすべて印刷したい場合は想像してください。

+0

が得られました。したがって、参照渡しまたは値渡しのオプションを指定すると、参照渡しが優先されます。 – marc

+1

@kris:Cは値渡しのみの言語です。最初の変種では、ポインタだけがコピーされ、2番目の変種では構造体全体がコピーされます。 –

+2

まず、Cでは「参照渡し」はありません。すべてが価値によって渡されます。渡されたもの(値によって)は異なっています。大抵の場合、ポインタを渡す方が良いのは、構造体コピーが潜在的に高価になる可能性があるためです。一方、 'save_struct_model_2()'を使うと、呼び出し側で 'honda'を変更することはできません。あなたが望むかもしれないし、そうでないかもしれません。一般的なルールとして、私はあなたに*良い理由がない限り、ポインタバージョン*を使用すると言うでしょう。 – usr

0

save_struct_model_1の関数では、構造体全体がアドレスによって別の関数に渡されます。つまり、構造体のアドレスだけが別の関数に渡されます。構造全体は、すべてのメンバーとその値を持つ別の関数に渡されません。したがって、この構造は呼び出された関数からそのアドレスによってアクセスできます。

save_struct_model_2関数では、構造体全体がvalueによって別の関数に渡されます。つまり、構造体全体がすべてのメンバーとその値を持つ別の関数に渡されます。したがって、この構造は呼び出された関数からアクセスできます。 C.

に非常に大きなプログラムを書きながらこの概念は
-1

は私がこれを行うと思う非常に便利です:

値でのconstポインタと通過構造体によって通過構造体の違いは、後者ということです
int //to singnal errors in printf 
save_struct_model_3(struct model const *s){ 
     //const to guarantee immutability 
     int r = 0; 
     r |= 0>printf("%s ", s->name); 
     r |= 0>printf("%d \n",s->year); 
     return -r; 
} 

非常に小さな構造体(より少ない間接参照)に対してはわずかに高速ですが、前者は他のすべての構造体(コピーなし)に対して高速です。

私は一度オーバヘッドを測定しましたが、x86_64では、構造体のサイズがint32_tの4倍以上になると値渡しが失われ始めます。ここで

私のベンチマーク結果である:

n_ints val/ns ptr/ns 
1 4.552 5.544 
2 4.748 5.336 
3 4.712 5.572 
4 5.556 5.460 << 
5 6.180 4.436 
6 5.252 5.424 
7 5.620 4.100 
8 4.316 4.164 
9 5.612 4.220 
10 6.656 4.656 
11 6.148 4.472 
12 6.708 4.708 
13 6.192 5.200 
14 8.560 4.652 
15 7.392 4.620 
16 8.512 4.728 
17 8.244 5.488 
18 10.108 5.360 
19 8.540 4.740 
20 10.028 5.468 
関連する問題