初期化されていないC文字列に警告は出ない 質問する

初期化されていないC文字列に警告は出ない 質問する

現在、小さな C プログラムのコンパイル/リンク中に GCC からエラーが発生しないのはなぜか疑問に思っています。

version.h次の文字列で宣言しました:

const char* const VERSION;

version.c変数の初期化を設定しました:

const char* const VERSION = "0.8 rev 213";

問題ありません。プログラムの残りの部分で文字列を使用できます。

c ファイルが見つからない場合、コンパイル/リンク中にエラーは発生しませんが、プログラムが変数にアクセスしようとすると、SIGSEGV (当然) で失敗します。

変数を設定する私の方法はVERSION正しいでしょうか、それとももっと良い方法があるのでしょうか? あるいは、コンパイル/リンク中にエラーが発生する可能性はありますか?

ベストアンサー1

あなたが持っている定義されたヘッダー内の変数を(単に宣言するのではなく)

このヘッダーを複数のソースファイルからインクルードした場合、動作は次のようになります。未定義以下は標準からの関連する引用です。

J.2 未定義の動作

外部リンケージを持つ識別子が使用されていますが、プログラム内にその識別子の外部定義が 1 つだけ存在しないか、または識別子が使用されず、その識別子の外部定義が複数存在します。

ここではGCC特有の(実際には多くのコンパイラに共通だが、それでも非標準)動作、つまり重複したコードのマージに依存しています。仮のデータ定義。および-fcommonGCC-fno-commonコンパイル フラグのヘルプを参照してください。すべてのコンパイラがこのように動作するわけではありません。歴史的に、これはリンカーの一般的な動作です。これは、C が登場する前の Fortran の動作だったためです。

この言語拡張を前提とすると、定義の 1 つ (明示的な初期化子を持つもの) は、変数を初期化して文字列リテラルを指します。ただし、この定義を省略すると、ゼロで初期化されたままになります。つまり、定数の null ポインターになります。あまり役に立ちません。

簡単に言うと、絶対にそんなことはしないでください。ヘッダーでグローバル変数を宣言(定義ではなく)するには、 を使用しますextern。そうして、他の場所で定義を省略しようとすると、おそらくリンカー エラーが発生します (標準ではこの違反の診断は要求されていませんが、既知の実装はすべて 1 つを生成します)。

おすすめ記事