C で構造体をポインターで渡すのではなく値で渡すことには欠点がありますか? 質問する

C で構造体をポインターで渡すのではなく値で渡すことには欠点がありますか? 質問する

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();

examine_data何らかの理由で、ほとんどの人は本能的に構造体 BLOB へのポインターを取得すると思いますが、その理由はわかりません。それでもポインターと整数を取得しますが、これらが一緒に使用される方がはるかに明確です。また、このget_data場合は、長さの入力値がなく、返される長さがなければならないため、前に説明した方法で混乱することは不可能です。

ベストアンサー1

小さな構造体 (例: point、rect) の場合、値渡しはまったく問題ありません。ただし、速度とは別に、大きな構造体を値で渡したり返したりする際に注意が必要な理由がもう 1 つあります。それは、スタック領域です。

Cプログラミングの多くは組み込みシステム向けで、メモリが貴重であり、スタックサイズはKBまたはバイト単位で測定されることがあります...構造体を値で渡したり返したりすると、それらの構造体のコピーがスタックに配置され、次のような状況が発生する可能性があります。このサイト...にちなんで名付けられました。

スタックの使用量が過剰であると思われるアプリケーションを見つけた場合、値渡しされる構造体は私が最初に探すものの 1 つです。

おすすめ記事