结构中未初始化的字段没有Clang警告

考虑以下结构:

typedef struct foo { int a; int b; } foo; 

我的编译器没有对以下语句发出警告:

 foo m = {300} 

为什么没有发出警告? 我期待一个警告,因为我没有为结构的最后一个字段提供任何值。

这是我的编译器调用:

 gcc -Wall -Wpadded -Wuninitialized -g bar.c 

这是我的gcc版本:

 Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn) Target: x86_64-apple-darwin15.0.0 Thread model: posix 

flipped_move字段是否只包含垃圾? 这样安全吗?

-Wmissing-field-initializers将警告您在struct初始化中缺少字段初始值设定项。

但是,如果您选择初始化没有值的结构,则看起来像clang那样标志不会警告您。 例如

 struct foo{ int a; }; int main(int argc, char **argv) { struct foo f = {}; return 0; } 

即使使用-Wmissing-field-initializers ,也不会发出警告。 如果您在这种情况下也想要警告,则应添加-Wgnu-empty-initializer

GCC

虽然你问过clang,但这也适用于GCC
传入-Wmissing-field-initializers时,GCC将为这两种情况发出警告。 GCC没有-Wgnu-empty-initializer标志。

-Wuninitialised警告未初始化的变量。 但是你的复合文字 已经完全初始化了。

C不支持部分初始化struct s和数组初始化器中的字段或未明确给出的复合文字自动设置为0 / 0.0 / null指针(取决于类型)。 所以编译器不需要警告。

也许在现代C中使用指定的初始化器而不是位置初始化器是更好的做法:

 (move){orig_c, curr_c, ... } 

将值存储到第一个,第二个等字段,无论它具有哪个名称及其类型。 如果您删除字段,但忘记删除值,则会导致问题:

 // from field removed (move){orig_c, curr_c, ... } 

将设置to和以下字段。 虽然这会为您的struct生成错误,但想象一下这些类型是兼容的。

指定的初始化程序没有此问题:

 (move){ .from = orig_c, .to = curr_c, ... } 

如果您from删除,如果您忘记更改该列表,则会收到有关未知字段名称的错误。 如果你忘了一个字段,你也会更容易看到。 这对于更大的struct尤其有用。


旁注:你的编译器不是 gcc,而是llvm / clang。 不幸的是,当他们出于兼容性原因更改工具链时,Apple将gcc链接到该编译器。 不好的想法,因为编译器完全兼容。

clang将不会警告你关于未初始化的结构成员,布尔或其他,即使使用-Weverything 。 这是一个演示。

 $ cc --version Apple LLVM version 7.3.0 (clang-703.0.31) Target: x86_64-apple-darwin15.5.0 Thread model: posix $ cat test.c #include  #include  typedef struct { int num1; bool flipped_moved; int num2; } Thing; void do_something(Thing *thing) { printf("%d %d %d\n", thing->num1, thing->num2, thing->flipped_moved); } int main () { Thing what; do_something(&what); return 0; } $ CFLAGS=-Weverything make cc -Weverything -Wall -g test.c -o test test.c:10:6: warning: no previous prototype for function 'do_something' [-Wmissing-prototypes] void do_something(Thing *thing) { ^ test.c:7:9: warning: padding struct 'Thing' with 3 bytes to align 'num2' [-Wpadded] int num2; ^ 2 warnings generated. $ ./test 1431815496 1771089974 1 

相反,如果用Thing what = {23};部分初始化的Thing what = {23}; 然后剩下的字段为零。

 $ ./test 23 0 0