部分的なイニシャライザ アプローチ (つまり ' { 0 }
') の 1 つの問題は、GCC がイニシャライザが不完全であることを警告することです (警告レベルが十分に高い場合、私は通常 ' ' を使用-Wall
し、しばしば ' ' を使用します-Wextra
)。指定されたイニシャライザのアプローチでは、その警告は表示されませんが、C99 はまだ広く使用されていません。ただし、これらのパーツは、おそらく Microsoft の世界を除いて、かなり広く利用されています。
私はアプローチを好む傾向があります:
static const struct sockaddr_in zero_sockaddr_in;
に続く:
struct sockaddr_in foo = zero_sockaddr_in;
静的定数で初期化子を省略したということは、すべてがゼロであることを意味しますが、コンパイラはウィッターしません (ウィッターすべきではありません)。代入では、コンパイラの生来のメモリ コピーが使用されます。これは、コンパイラに深刻な欠陥がない限り、関数呼び出しよりも遅くはなりません。
GCCは時間の経過とともに変化しました
GCC バージョン 4.4.2 から 4.6.0 は、GCC 4.7.1 とは異なる警告を生成します。具体的には、GCC 4.7.1 は= { 0 }
初期化子を「特殊なケース」として認識し、文句を言いませんが、GCC 4.6.0 などは文句を言いました。
ファイルを検討してくださいinit.c
:
struct xyz
{
int x;
int y;
int z;
};
struct xyz xyz0; // No explicit initializer; no warning
struct xyz xyz1 = { 0 }; // Shorthand, recognized by 4.7.1 but not 4.6.0
struct xyz xyz2 = { 0, 0 }; // Missing an initializer; always a warning
struct xyz xyz3 = { 0, 0, 0 }; // Fully initialized; no warning
GCC 4.4.2 (Mac OS X 上) でコンパイルすると、警告は次のようになります。
$ /usr/gcc/v4.4.2/bin/gcc -O3 -g -std=c99 -Wall -Wextra -c init.c
init.c:9: warning: missing initializer
init.c:9: warning: (near initialization for ‘xyz1.y’)
init.c:10: warning: missing initializer
init.c:10: warning: (near initialization for ‘xyz2.z’)
$
GCC 4.5.1 でコンパイルすると、警告は次のようになります。
$ /usr/gcc/v4.5.1/bin/gcc -O3 -g -std=c99 -Wall -Wextra -c init.c
init.c:9:8: warning: missing initializer
init.c:9:8: warning: (near initialization for ‘xyz1.y’)
init.c:10:8: warning: missing initializer
init.c:10:8: warning: (near initialization for ‘xyz2.z’)
$
GCC 4.6.0 でコンパイルすると、警告は次のようになります。
$ /usr/gcc/v4.6.0/bin/gcc -O3 -g -std=c99 -Wall -Wextra -c init.c
init.c:9:8: warning: missing initializer [-Wmissing-field-initializers]
init.c:9:8: warning: (near initialization for ‘xyz1.y’) [-Wmissing-field-initializers]
init.c:10:8: warning: missing initializer [-Wmissing-field-initializers]
init.c:10:8: warning: (near initialization for ‘xyz2.z’) [-Wmissing-field-initializers]
$
GCC 4.7.1 でコンパイルすると、警告は次のようになります。
$ /usr/gcc/v4.7.1/bin/gcc -O3 -g -std=c99 -Wall -Wextra -c init.c
init.c:10:8: warning: missing initializer [-Wmissing-field-initializers]
init.c:10:8: warning: (near initialization for ‘xyz2.z’) [-Wmissing-field-initializers]
$
上記のコンパイラは私がコンパイルしたものです。Apple が提供するコンパイラは、名目上 GCC 4.2.1 と Clang です。
$ /usr/bin/clang -O3 -g -std=c99 -Wall -Wextra -c init.c
init.c:9:23: warning: missing field 'y' initializer [-Wmissing-field-initializers]
struct xyz xyz1 = { 0 };
^
init.c:10:26: warning: missing field 'z' initializer [-Wmissing-field-initializers]
struct xyz xyz2 = { 0, 0 };
^
2 warnings generated.
$ clang --version
Apple clang version 4.1 (tags/Apple/clang-421.11.65) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin11.4.2
Thread model: posix
$ /usr/bin/gcc -O3 -g -std=c99 -Wall -Wextra -c init.c
init.c:9: warning: missing initializer
init.c:9: warning: (near initialization for ‘xyz1.y’)
init.c:10: warning: missing initializer
init.c:10: warning: (near initialization for ‘xyz2.z’)
$ /usr/bin/gcc --version
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$
以下のコメントでSecurityMattが指摘しているように、memset()
メモリから構造体をコピーすることの利点は、メモリからのコピーがよりコストがかかり、1 つではなく 2 つのメモリ位置 (ソースとコピー先) にアクセスする必要があることです。比較すると、値をゼロに設定すると、ソースのメモリにアクセスする必要がなくなり、最新のシステムではメモリがボトルネックになります。そのため、単純なイニシャライザ (同じ値 (通常はすべてゼロ バイト) がターゲット メモリに配置される) の場合、memset()
コーディングはコピーよりも高速である必要があります。初期化子が値の複雑な組み合わせ (すべてがゼロバイトではない) である場合、表記のコンパクトさと信頼性のために、初期化子を優先してバランスを変更できます。
切り詰められた答えは 1 つもありません。私はまだイニシャライザを使用する傾向がありますが、memset()
多くの場合有効な代替手段です。