结构中未初始化的字段没有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