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

时间:2016-06-05 01:20:37

标签: c struct 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字段是否只包含垃圾?这样安全吗?

3 个答案:

答案 0 :(得分:7)

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

C不支持部分初始化struct和数组初始值中的字段或未明确给出的复合文字自动设置为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链接到了该编译器。不好的想法,因为编译器完全兼容。

答案 1 :(得分:2)

-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标志。

答案 2 :(得分:1)

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 <stdio.h>
#include <stdbool.h>

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

相反,如果使用what部分初始化Thing what = {23};,则其余字段为零&#39; d。

$ ./test
23 0 0