構造体をゼロ/ nullに初期化/リセット


92
struct x {
    char a[10];
    char b[20];
    int i;
    char *c;
    char *d[10];
};

私はこの構造体を埋めて、値を使用しています。次の繰り返しで、私はにすべてのフィールドをリセットしたい0null、私はそれを再利用を開始する前に。

どうやってやるの?使用できますmemsetか、それともすべてのメンバーを通過してから個別に実行する必要がありますか?

回答:


109

初期値で構造体のconst staticインスタンスを定義し、リセットしたいときはいつでもこの値を変数に割り当てるだけです。

例えば:

static const struct x EmptyStruct;

ここでは静的初期化を使用して初期値を設定していますが、異なる初期値が必要な場合はstruct初期化子を使用できます。

次に、ループを回るたびに次のように記述できます。

myStructVariable = EmptyStruct;

1
@David Heffernan:memsetすべてをリセットしたいだけの場合に使用するよりも良いです0か?
ハリー、2011

9
@hari私はこのアプローチを自分で好みます。使うmemsetと汚れてきます。可能な限り、メモリレイアウトをコンパイラに任せたいと思います。厳密に言えば、そのような使用はmemset移植性がありませんが、実際に重要な場所でコードをコンパイルしたことがあれば、私は驚かれるでしょう。したがって、必要に応じてmemsetを安全に使用できます。
デビッドヘ

2
@hari、デフォルトの初期化値(オブジェクトファクトリパターンのようなもの)を提供するため、概念的にはより良い
Diego Sevilla

1
@cnicutar私はこれを知っています。私の答えはmemsetを使用しないことを推奨していることに注意してください。null値を割り当てる手段としてmemsetを使用することの非移植性を指摘した場所に関するコメントにも注意してください。私の以前のコメントは、0ビットが常に浮動小数点のゼロに対応するという現実を指摘しているだけです。
David Heffernan

1
@ kp11引用してください
David Heffernan

85

最新のC(C99)を使用している場合にこのようなことを行う方法は、複合リテラルを使用することです。

a = (const struct x){ 0 };

これは、Davidのソリューションにいくぶん似ていますが、空の構造を宣言したり、それを宣言するかどうかを心配したりする必要はありませんstatic。私が使用したconstようにを使用する場合、コンパイラーは、必要に応じて複合リテラルを読み取り専用ストレージに静的に割り当てることができます。


それはスタックにxのインスタンスを作成し、それをaにコピーしますか?問題になる可能性のある大きな構造/小さなスタックの場合。
エティエンヌ2014年

1
すべての最適化と同様に、これは完全にコンパイラに依存するため、コンパイラが生成するものを確認する必要があります。「通常」はそうではない最新のコンパイラでは、初期化を非常にうまくトレースでき、必要なことだけを実行できます。(そして、実際のスローダウンを測定する前に、そのようなことが問題であるとは思わないでください。通常はそうではありません。)
Jens Gustedt

3
「イニシャライザがありません」という警告は本当に偽物です。C標準は、何が発生するかを正確に規定{ 0 }し、デフォルトの初期化子としてを予測しています。その警告をオフに切り替えてください、それは偽の誤警報です。
Jens Gustedt、2015

1
@JensGustedtこの型キャストは本当に必要ですか?このように書けませんか?struct xa =(const){0};
Patrick

1
@Patrick、構文は似ていますが、これはキャストではなく「複合リテラル」です。また、初期化と割り当てを混同しています。
イェンス・ガステッド2017

58

上記のすべてよりも優れているのは、構造体の初期化に標準C仕様を使用することです。

struct StructType structVar = {0};

ここにすべてのビットがゼロになります。


13
私はあなたがループの周りで毎回そうすることができるとは思いません
デビッド・ヘファーナン

2
これは確かに機能するはずです。しかし、残念ながら、gccとg ++はそれについて不満を言っています。gccは警告を生成し、g ++はエラーを生成します。私はgccとg ++がこれに誤りがあることを知っていますが(それらは標準C仕様に準拠しているはずです)、それにもかかわらず、優れた移植性のために、そのような制限を考慮することは必須です。
シアン2015年

3
@Cyan {}C ++で使用できます。gcc開発者は、C ++がサポートすることになって{0}いるのかどうかわからないようで、私は標準のその部分に精通していません。
Matthew Read

@Matthewは:であまりにも多くの移植性の問題があったので、はい、実際に、私は、memsetの()を使用して終了{0}{}。C&C ++標準が明確でこの問題について同期しているかどうかはわかりませんが、コンパイラはそうではないようです。
シアン2015年

このような場合、これは機能しますか?struct StructType structVar = malloc (sizeof(StructType)); structVar ={0}
サムトーマス

34

Cでは、structusingのメモリをゼロにするのが一般的な慣用法memsetです。

struct x myStruct;
memset(&myStruct, 0, sizeof(myStruct));

厳密に言えば、NULLマシン上のポインターが整数値0で表されると想定しているため、これは移植可能だとは思わないが、ほとんどのマシンでこれが当てはまるため、広く使用されている。

CからC ++に移行する場合は、すべてのオブジェクトでこの手法を使用しないように注意してください。C ++は、メンバー関数も継承もないオブジェクトに対してのみこれを正当にします。


2
C標準では、NULLは常に0であると規定されています。事前に設定された無効なアドレスが文字通り0ではないようにマシンが設計されている場合、そのアーキテクチャのコンパイラはコンパイル中に調整する必要があります。
ケビンM

8
@KevinMはい、記号「0」は、たとえすべてゼロであっても、常にNULLポインターに対応しています。しかし、memsetを使用してビットをゼロに設定した場合、コンパイラーができることは何もありません。
Adrian Ratnapala

「C ++は、メンバー関数も継承もないオブジェクトに対してのみこれを正当にします。」タイプが「プレーンな古いデータ」と見なされるかどうかについてです。基準は、C ++言語のバージョンによって異なります。
Max Barraclough

19

C99準拠のコンパイラを使用している場合は、

mystruct = (struct x){0};

それ以外の場合は、David Heffernanが書いたことを行う必要があります。つまり、次のように宣言します。

struct x empty = {0};

そしてループで:

mystruct = empty;

6

memset構造体のサイズで使用できます:

struct x x_instance;
memset (&x_instance, 0, sizeof(x_instance));

1
ここではキャストは必要ないと思います。それは...ですか?
templatetypedef

まあ、私はC ++に慣れているので...まあ、それはC ++でも機能するので、負担とは思わない。
ディエゴセビリア

ええ、私は十分に具体的ではありませんでした。これは、cv修飾Tへの任意のポインタで、cv修飾void *に変換できます。データポインター、関数ポインターは、まったく別の問題です。称賛@Kevin
Marcus

memsetはオプションですが、それを使用するときは、書き込まれるメモリが3番目のパラメータと正確に同じサイズであることを確認する必要があります。そのため、実際のオブジェクトのサイズではなく、実際のオブジェクトのサイズを参照することをお勧めしますそれが現在あることを知っます。IOWの方memset (&x_instance, 0, sizeof(x_instance));がはるかに良い選択です。ところで:(void*)キャストはC ++でも不必要です。
ウルフ

(質問の面倒を見逃してすみません
Wolf

5

空のセット({})を変数に割り当てるだけでよいと思います。

struct x instance;

for(i = 0; i < n; i++) {
    instance = {};
    /* Do Calculations */
}


-1

ここに画像の説明を入力してください。

typedef struct {
    uint8_t messType;
    uint8_t ax;  //axis
    uint32_t position;
    uint32_t velocity;
}TgotoData;

TgotoData tmpData = { 0 };

何もゼロではありません。


1
これは、「すべてのフィールドを0にリセットするにはどうすればよいですか」という質問に答えようとするものではありません
MM
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.