gcc 编译器为何掷回这个警告:“缺少初始值设定项”?结构没有初始化吗?

wko9yo5t  于 2022-11-13  发布在  其他
关注(0)|答案(5)|浏览(267)

我正在为一个程序创建某种前端。为了启动程序,我使用了CreateProcess()调用,它接收一个指向STARTUPINFO结构的指针。为了初始化该结构,我通常会做以下操作:

STARTUPINFO startupInfo = {0}; // Or even '\0'.
startupInfo.cb = sizeof(startupInfo);

当使用GCC编译程序时,启用这些警告-Wall -Wextra,它会给我一个警告,说有一个指向第一行的初始化器丢失。

warning: missing initializer
warning: (near initialization for 'startupInfo.lpReserved')

所以我最终做了:

STARTUPINFO startupInfo;
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);

这样编译器就不会给予任何警告。问题是,这两种初始化结构的方法有什么区别?使用第一种方法,结构不是被初始化了吗?你会推荐哪一种方法?

wsxa1bj1

wsxa1bj11#

GCC只是过于偏执了--在我看来没有什么好的理由,但是GCC维护者确实比我更了解C的细微差别。
请在GCC邮件列表中查看关于该问题的小讨论:

****1998年7月1日第1/3期。

      • 1998年7月2日第2/3期。
        ****1998-07-02. 3/3.

但底线是--仅用{0}初始化结构体实际上将零初始化整个结构体。
C99标准在6.7.8/21“初始化-语义”中说明了以下内容:
如果用大括号括起来的列表中的初始值设定项比聚合的元素或成员少,或者用于初始化已知大小的数组的字符串文字中的字符比数组中的元素少,则聚合的其余部分应隐式初始化为与具有静态存储持续时间的对象相同。
C90在6.5.7中的表述基本相同,只是措辞略有不同(换句话说,C99在这里没有添加新内容)。
另请注意,在C++中,这是经过扩展的,因此一组空大括号“{}“将对对象执行值初始化,因为在某些情况下(就像模板一样),因为您甚至不知道一个类型可能包含哪些成员或有多少成员。因此,这不仅是一个好的实践,但有时需要一个比对象可能拥有的成员数更短的初始化器列表。

iaqfqrcu

iaqfqrcu2#

对于C++程序中的GCC,通过将结构初始化为

STARTUPINFO startupInfo = STARTUPINFO();
  • 我几天前就这么做了
tquggr8v

tquggr8v3#

您要求使用-Wall和-Wextra提供尽可能多的警告。
在这种情况下,您会收到一个警告,告诉您没有指定所有字段,这完全有效,但可能是无意的。
您可以加入-Wno-missing-field-initializer来隐藏这个警告。

polhcujo

polhcujo4#

网页 How to initialise structures to all-elements-zero-or-null 详细讨论了根本问题:
作为一种解决办法,我目前的解决方案是选择性地禁止此警告:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
STARTUPINFO startupInfo = {0};
#pragma clang diagnostic pop

遗憾的是,这只在Clang中有效,在GCC中似乎不起作用。

z3yyvxxp

z3yyvxxp5#

在C++中,你可以使用boost::initialized_value来消除这个警告。所以我不知道在你的情况下这是否会引起任何其他警告。这样你就不必禁用警告了。
示例:

T bla = boost::initialized_value;

相关问题