78

例如,如果somestruct有三个整数成员,我一直认为在 C(或 C++)函数中这样做是可以的:

somestruct s = {123,};

第一个成员将被初始化为 123,最后两个成员将被初始化为 0。我经常对自动数组做同样的事情,写入数组int arr[100] = {0,};中的所有整数都初始化为零。


最近我在GNU C 参考手册中读到:

如果不初始化结构变量,效果取决于它是否具有静态存储(请参阅存储类说明符)。如果是,则整数类型的成员初始化为 0,指针成员初始化为 NULL;否则,结构成员的值是不确定的。


有人可以告诉我 C 和 C++ 标准对部分自动结构和自动数组初始化有什么看法吗?我在 Visual Studio 中执行上述代码没有问题,但我想与 gcc/g++ 兼容,也许还有其他编译器。谢谢

4

3 回答 3

112

链接的 gcc 文档没有谈论Partial Initialization它只是谈论(Complete)InitializationNo Initialization

什么是部分初始化?

标准没有定义对象的部分初始化,要么有完全初始化,要么没有初始化。部分初始化是一个非标准术语,通常是指您提供一些初始化器但不是全部的情况,即:初始化器少于数组的大小或正在初始化的结构元素的数量。

例子:

int array[10] = {1,2};                    //Case 1:Partial Initialization

什么是(完全)初始化或无初始化?

初始化意味着在创建变量的同时为创建的变量提供一些初始值。即:在相同的代码语句中。

例子:

int array[10] = {0,1,2,3,4,5,6,7,8,9};    //Case 2:Complete Initialization
int array[10];                            //Case 3:No Initialization

引用的段落描述了Case 3.

有关 Partial Initialization( Case 1) 的规则由标准很好地定义,这些规则不依赖于被初始化变量的存储类型。
AFAIK,所有主流编译器都 100% 遵守这些规则。


有人可以告诉我 C 和 C++ 标准对部分自动结构和自动数组初始化有什么看法吗?

C 和 C++ 标准保证即使整数数组位于自动存储中,并且如果大括号括起来的列表中的初始化程序较少,那么未初始化的元素也必须初始化为0.

C99 标准 6.7.8.21

如果大括号括起来的列表中的初始值设定项少于聚合的元素或成员,或者用于初始化已知大小数组的字符串文字中的字符少于数组中的元素,则聚合的其余部分应隐式初始化与具有静态存储持续时间的对象相同。


在 C++ 中,规则的表述略有不同。

C++03 标准 8.5.1 聚合
第 7 段:

如果列表中的初始化器少于聚合中的成员,则每个未显式初始化的成员都应进行值初始化(8.5)。[例子:

 struct S { int a; char* b; int c; };
 S ss = { 1, "asdf" };

ss.a使用、 和形式的表达式的值进行初始化1,即. ]ss.b"asdf"ss.cint()0

虽然值初始化在
C++03 8.5 Initializers
Para 5 中定义:

对T 类型的对象进行值初始化意味着:
— 如果 T 是具有用户声明的构造函数(12.1)的类类型(第 9 条),则调用 T 的默认构造函数(如果 T没有可访问的默认构造函数);
— 如果 T 是没有用户声明的构造函数的非联合类类型,则 T 的每个非静态数据成员和基类组件都是值初始化的;
— 如果 T 是一个数组类型,那么每个元素都是值初始化的;
— 否则,对象被零初始化

于 2012-05-31T06:13:35.253 回答
18

在 C 中,对象永远不会被部分初始化——如果它们的任何部分被初始化,则整个对象(以及递归的所有子对象)都会被初始化。如果没有提供显式初始化器,则元素被初始化为“适当类型的零”。

您问题中的引用是指当整个对象的初始化程序完全被排除在外时,而不是当子对象缺少初始化程序时。例如,假设arr具有自动存储持续时间,那么:

int arr[100] = { 123 };

初始化arr[0]to和to123的所有其他元素。而这:arr0

int arr[100];

留下arr未初始化的每个元素。引用所指的是后一种情况。

于 2012-05-31T06:31:18.643 回答
5

最新的 gcc 版本还允许同时“部分”初始化和 zeromem:

typedef struct{
  int a,b,c;
}T;

T s = {0, .b=5};

结构成员现在将具有以下值:a=0, b=5, c=0

我没有任何关于其他编译器是否允许这样做的信息:p

于 2013-02-26T19:44:34.673 回答