web-dev-qa-db-ja.com

コンパイラがなぜ「イニシャライザがありません」という警告を投げるのですか?構造は初期化されていませんか?

私はプログラムのある種のフロントエンドを作成しています。プログラムを起動するには、CreateProcess()呼び出しを使用しています。これは、とりわけSTARTUPINFO構造体へのポインターを受け取ります。使用した構造を初期化するには:

STARTUPINFO startupInfo = {0}; // Or even '\0'.
startupInfo.cb = sizeof(startupInfo);

これらの一連の警告を有効にするGCCでプログラムをコンパイルする場合-Wall -Wextra最初の行を指している初期化子が見つからないという警告が表示されます。

warning: missing initializer
warning: (near initialization for 'startupInfo.lpReserved')

だから私はやったこと:

STARTUPINFO startupInfo;
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);

そして、このようにコンパイラは警告を出しません。問題は、構造を初期化するこれらの方法の違いは何ですか?最初の方法を使用して、構造は初期化されていませんか?どちらをお勧めしますか?

68
Shantia

GCCは過度に妄想的です-私の意見では正当な理由はありませんが、GCCのメンテナーが私が行うCのニュアンスについてもっと多くを知っていることは確かに真実です。

GCCメーリングリストの問題に関するこの小さな議論のスレッドを参照してください。

一番下の行-構造体を{0}だけで初期化すると、実際にはすべてがゼロで初期化されます。

C99標準では、6.7.8/21「初期化-セマティクス」で次のように記述されています。

ブレースで囲まれたリストの初期化子が集合体の要素またはメンバーより少ない場合、または既知のサイズの配列を初期化するために使用される文字列リテラルの文字が配列内の要素より少ない場合、集合体の残りは静的ストレージ期間を持つオブジェクトと同じように暗黙的に初期化されます。

C90は、6.5.7でも基本的に同じ文言であります(言い換えると、C99は新しいものを追加しませんでした)。

また、C++では、空のブレースセット "{}"がオブジェクトの値の初期化を実行するように拡張されていることに注意してください。型が持つ可能性のあるメンバーの数。したがって、それは良い習慣であるだけでなく、オブジェクトが持つかもしれないメンバーの数よりも短い初期化リストを持つことが時々必要です。

82
Michael Burr

これは、構造を次のように初期化することにより、C++プログラムのGCCで簡単に修正できます。

STARTUPINFO startupInfo = STARTUPINFO();
  • 数日前にまさにこれをやった
17
dmityugov

-Wall -Wextraを使用して、できるだけ多くの警告を要求しました。

この場合、すべてのフィールドを指定しなかったことを示す警告が表示されます。これは完全に有効ですが、意図しない可能性があります。

-Wno-missing-field-initializersを追加することにより、この警告を抑制することができます

13
ecotax

このWebページでは、根本的な問題について詳細に説明しています。 http://ex-parrot.com/~chris/random/initialise.html

回避策として、私の現在の解決策は、この警告を選択的に抑制することです。

#pragma clang diagnostic Push
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
STARTUPINFO startupInfo = {0};
#pragma clang diagnostic pop

悲しいことに、これはclangでのみ機能し、GCCでは機能しないようです。

9
JanX2

C++では、boost::initialized_valueを使用してこの警告を取り除くことができます。 boost;の警告がオフになっています。したがって、これが他の警告を引き起こすかどうかはわかりません。この方法では、警告を無効にする必要はありません。

例:

T bla = boost::initialized_value;
1