C 和 C++ : 自动结构的部分初始化

C and C++ : Partial initialization of automatic structure

本文关键字:初始化 结构 C++      更新时间:2023-10-16

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

somestruct s = {123,};

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


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

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


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

链接的 gcc 文档没有谈论部分初始化,它只谈论(完成)初始化或不初始化

什么是部分初始化?

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

例:

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的行为。

关于部分初始化(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" };

1 初始化ss.a,用 "asdf" 初始化ss.b,用形式为 int() 的表达式的值初始化ss.c,即 0

当值初始化在 中定义时,
C++03 8.5 初始值设定项
第5段:

对 T 类型的对象进行值初始化意味着:
— 如果 T 是具有用户声明的构造函数 (12.1) 的类类型(子句 9),则调用 T 的默认构造函数(如果 T 无法访问,则初始化格式不正确 默认构造函数);
— 如果 T 是没有用户声明构造函数的非联合类类型,则每个非静态 T 的数据成员和基类组件是值初始化的;
— 如果 T 是数组类型,则每个元素都是值初始化的;
— 否则,对象初始化为零

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

您问题中的引号是指当整个对象的初始化器被完全省略时,而不是当子对象缺少初始化器时。 例如,假设arr具有自动存储持续时间,则:

int arr[100] = { 123 };

arr[0]初始化为 123,将arr的所有其他元素初始化为 0 。 而这:

int arr[100];

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

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

typedef struct{
  int a,b,c;
}T;
T s = {0, .b=5};

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

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