考虑以下结构:
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字段是否只包含垃圾?这样安全吗?
答案 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
。
虽然你问过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