来自GCC但非Clang的复合文字和指定初始值设定项警告
使用来自GCC但非Clang的复合文字和指定初始值设定项警告,c,gcc,clang,designated-initializer,compound-literals,C,Gcc,Clang,Designated Initializer,Compound Literals,使用gcc-std=c99-Wextra编译这段代码: #include <stdio.h> struct T { int a; int *b; int c; }; int main(void) { struct T t = {.b = ((int []){1, 1})}; printf("%d\n", t.b[1]); return 0; } 但是,指定的初始值设定项应该将其余成员的初始值设定为零,即使它们已被指定 为什么要发
gcc-std=c99-Wextra编译这段代码:
#include <stdio.h>
struct T {
int a;
int *b;
int c;
};
int main(void)
{
struct T t = {.b = ((int []){1, 1})};
printf("%d\n", t.b[1]);
return 0;
}
但是,指定的初始值设定项应该将其余成员的初始值设定为零,即使它们已被指定
为什么要发出警告?(clang
编译同一段代码时没有警告)
为什么要发出警告
因为-Wmissing字段初始值设定项是由-Wextra
设置的,您可以在gcc
调用中设置后者
-Wextra
很挑剔,-Wmissing字段初始值设定项
甚至不是-Wall
的元素
仅省略一些字段初始值设定项而不是全部是错误的来源。在一个包含数百个元素的数组/结构中,您只需初始化其中的一些元素,那么仅仅通过查看代码就几乎不可能掌握这些元素。这看起来像是一个gcc“一致性错误”,下面是中的相关代码片段
代码的目的似乎是警告任何属性构造函数是否有未填充的字段。在元素“a”上没有得到警告的事实很可能就是这里的“一致性错误”
如果-Wextra
打算打开缺少初始值设定项警告,那么它已经打开了。问题是,“缺少初始值设定项警告”是否应排除省略的属性?似乎gcc和clang对此意见不一致——他们可以这么做吗
这可能不是你想要的答案。。但希望这有助于你了解情况。GCC团队有一个一致性缺陷,但在这些情况下,他们的代码的意图似乎是警告,而根据经验,clang不会。以前没有人发现过它——仅此而已。请注意,复合文字周围不需要括号。复合文字似乎是bug的一部分;使用struct T={.b=&T.a}例如,代码>不会生成警告。单元素数组(复合文字)也足够了。它似乎也是“仅在用复合文字初始化的元素之后的元素”。添加intd代码>在c
之后,并且没有关于d
的投诉。(在前面或后面添加更多的整数,得到抱怨的仍然是复合文字后面的一个元素。)@JonathanLeffler:如果后面有成员,它总是抱怨最后一个设计初始值设定项。如果最后一个设计初始值设定项后面没有任何内容,它也不会抱怨。例如:struct{inta;int*b;intc;int*e;/*intf;*/}代码>和struct T T={.b=((int[]){1,1}),.e=((int[]){2,3})代码>这不会。但是删除关于e
的注释,不再是关于b
的注释。遵守网站上的规则-其中之一是你需要提交预处理的源代码,因此最小化产生问题所需的标题可以最小化错误报告的大小。想一想服用类固醇的麦克维@M.M即使这是标志的目的,其余的成员也应该自动初始化,这样就不需要发出警告了,不是吗?我的代码也受到这个讨厌的bug的影响。但是请注意,您可以使用#pragma GCC diagnostic ignored“-Wmissing field initializers”
作为(临时)解决方法,在每个文件的基础上抑制警告。此警告在GCC中仅被破坏,请参阅。如您所见,不省略任何初始值设定项仍然可以触发警告。那是5年前的事了,但gcc主干仍然显示出同样的错误。我无法证实这一点。将行更改为struct T={.b=((int[]){1,1}),.c=1}
这样c
也被初始化,警告就会消失。不过,警告是易变的,不可信。很多误报。
demo.c:11:12: warning: missing initializer for field ‘c’ of ‘struct T’ [-Wmissing-field-initializers]
struct T t = {.b = ((int []){1, 1})};
^
demo.c:6:9: note: ‘c’ declared here
int c;
^
gcc version 6.3.0 20170516 (Debian 6.3.0-18)
clang version 3.8.1-24 (tags/RELEASE_381/final)
7436 /* Warn when some struct elements are implicitly initialized to zero. */
7437 if (warn_missing_field_initializers
7438 && constructor_type
7439 && TREE_CODE (constructor_type) == RECORD_TYPE
7440 && constructor_unfilled_fields)
7441 {
7442 bool constructor_zeroinit =
7443 (vec_safe_length (constructor_elements) == 1
7444 && integer_zerop ((*constructor_elements)[0].value));
7445
7446 /* Do not warn for flexible array members or zero-length arrays. */
7447 while (constructor_unfilled_fields
7448 && (!DECL_SIZE (constructor_unfilled_fields)
7449 || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
7450 constructor_unfilled_fields = DECL_CHAIN (constructor_unfilled_fields);
7451
7452 if (constructor_unfilled_fields
7453 /* Do not warn if this level of the initializer uses member
7454 designators; it is likely to be deliberate. */
7455 && !constructor_designated
7456 /* Do not warn about initializing with ` = {0}'. */
7457 && !constructor_zeroinit)
7458 {
7459 if (warning_at (input_location, OPT_Wmissing_field_initializers,
7460 "missing initializer for field %qD of %qT",
7461 constructor_unfilled_fields,
7462 constructor_type))
7463 inform (DECL_SOURCE_LOCATION (constructor_unfilled_fields),
7464 "%qD declared here", constructor_unfilled_fields);
7465 }
7466 }