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

dyl*_*unn 3 c struct clang

考虑以下结构:

typedef struct foo {
    int a;
    int b;
} foo;
Run Code Online (Sandbox Code Playgroud)

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

foo m = {300}
Run Code Online (Sandbox Code Playgroud)

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

这是我的编译器调用:

gcc -Wall -Wpadded -Wuninitialized -g bar.c
Run Code Online (Sandbox Code Playgroud)

这是我的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
Run Code Online (Sandbox Code Playgroud)

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

too*_*ite 8

-Wuninitialised警告未初始化的变量.但是,你的复合文字非常好完全初始化.

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

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

(move){orig_c, curr_c, ... }
Run Code Online (Sandbox Code Playgroud)

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

// from field removed
(move){orig_c, curr_c, ... }
Run Code Online (Sandbox Code Playgroud)

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

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

(move){ .from = orig_c, .to = curr_c, ... }
Run Code Online (Sandbox Code Playgroud)

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


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


Jas*_*itz 5

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

但是,在 clang 上,如果您选择初始化没有值的结构,该标志似乎不会警告您。例如

struct foo{
  int a;
};

int main(int argc, char **argv) {
  struct foo f = {};
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

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

海湾合作委员会

尽管您询问了 clang,但这也适用于 GCC,
当您传入 时,GCC 会针对这两种情况发出警告-Wmissing-field-initializers-Wgnu-empty-initializerGCC没有标志。