ポインターを渡すのではなく、C で構造体を値で渡すことの欠点はありますか?
構造体が大きい場合、大量のデータをコピーするというパフォーマンス上の側面があることは明らかですが、構造体が小さい場合は、関数にいくつかの値を渡すのと基本的に同じにする必要があります。
戻り値として使用すると、さらに興味深いものになるかもしれません。C では、関数からの戻り値は 1 つしかありませんが、多くの場合、複数の値が必要になります。したがって、簡単な解決策は、それらを構造体に入れて返すことです。
これに賛成または反対の理由はありますか?
ここで私が話していることは誰にも明らかではないかもしれないので、簡単な例を挙げます。
C でプログラミングしている場合、遅かれ早かれ次のような関数を書き始めるでしょう。
void examine_data(const char *ptr, size_t len)
{
...
}
char *p = ...;
size_t l = ...;
examine_data(p, l);
これは問題ではありません。唯一の問題は、すべての関数で同じ規則を使用するために、パラメーターの順序について同僚と同意する必要があることです。
しかし、同じ種類の情報を返したい場合はどうなるでしょうか? 通常、次のようなものが得られます。
char *get_data(size_t *len);
{
...
*len = ...datalen...;
return ...data...;
}
size_t len;
char *p = get_data(&len);
これは問題なく機能しますが、はるかに問題があります。戻り値は戻り値ですが、この実装ではそうではありません。上記から、関数 get_data が len が指すものを見ることが許可されていないことを伝える方法はありません。また、値が実際にそのポインターを介して返されることをコンパイラーにチェックさせるものは何もありません。そのため、来月、他の誰かがコードを正しく理解せずに (ドキュメントを読んでいなかったために) コードを変更すると、気付かないうちにコードが壊れたり、ランダムにクラッシュしたりします。
だから、私が提案する解決策は単純な構造体です
struct blob { char *ptr; size_t len; }
例は次のように書き直すことができます。
void examine_data(const struct blob data)
{
... use data.tr and data.len ...
}
struct blob = { .ptr = ..., .len = ... };
examine_data(blob);
struct blob get_data(void);
{
...
return (struct blob){ .ptr = ...data..., .len = ...len... };
}
struct blob data = get_data();
なんらかの理由で、ほとんどの人は本能的に inspect_data に構造体 blob へのポインターを持たせると思いますが、その理由はわかりません。ポインターと整数は引き続き取得されますが、それらが一緒になることははるかに明確です。get_data の場合、長さの入力値がなく、長さが返される必要があるため、前に説明した方法で混乱することはありません。