C和C ++:自动结构的部分初始化
例如,如果somestruct
有三个整数成员,我一直认为可以在C(或C ++)函数中做到这一点:
somestruct s = {123,};
第一个成员将被初始化为123,最后两个将被初始化为0.我经常对自动数组做同样的事情,编写int arr[100] = {0,};
所以数组中的所有整数都被初始化为零。
最近我在GNU C参考手册中读到:
如果不初始化结构variables,效果取决于它是否具有静态存储(请参阅存储类说明符)。 如果是的话,带整型的成员初始化为0,指针成员初始化为NULL; 否则,结构的成员的价值是不确定的。
有人可以告诉我关于部分自动结构和自动数组初始化的C和C ++标准说的吗? 我在Visual Studio中做了上面的代码没有问题,但我想兼容gcc / g ++,也可能是其他编译器。 谢谢
链接的海湾合作委员会文件不谈论部分初始化它只是说(完成)初始化或没有初始化 。
什么是部分初始化?
标准没有定义对象的部分初始化,有完整的初始化或没有初始化。 部分初始化是一个非标准的术语,它通常指的是你提供了一些初始化的情况,但不是全部,即:比数组的大小或被初始化的结构元素的数目更less的初始化。
例:
int array[10] = {1,2}; //Case 1:Partial Initialization
什么是(完整)初始化或不初始化?
初始化意味着在正在创build的同时为正在创build的variables提供一些初始值。 即:在相同的代码语句中。
例:
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
)的规则由标准定义,这些规则不依赖于被初始化variables的存储types。
AFAIK,所有主stream编译器都符合这些规则。
有人可以告诉我关于部分自动结构和自动数组初始化的C和C ++标准说的吗?
C和C ++标准保证,即使一个整数数组位于自动存储器上,并且如果大括号包含列表中的初始化器较less,那么未初始化的元素也必须初始化为0
。
C99标准6.7.8.21
如果大括号包含的列表中的初始值设定项less于聚合的元素或成员,或者用于初始化比数组中的元素大小的数组的stringstring中的较less字符,则聚合的其余部分应被隐式地初始化为具有静态存储持续时间的对象。
在C ++中,规则有一点区别。
C ++ 03标准8.5.1聚合
第7段:
如果列表中的初始化器比聚合中的成员less,那么未明确初始化的每个成员都应进行值初始化 (8.5)。 [例:
struct S { int a; char* b; int c; }; S ss = { 1, "asdf" };
初始化
ss.a
为1
,ss.b
为"asdf"
,ss.c
为int()
forms的expression式的值,即0
。 ]
在初始化值定义中,
C ++ 03 8.5初始化器
第5段:
为了初始化 Ttypes的对象,意味着:
– 如果T是一个具有用户声明的构造函数(12.1)的类types(第9章),那么将调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化为格式错误)。
– 如果T是没有用户声明的构造函数的非联合类types,则T的每个非静态数据成员和基类组件都被初始化;
– 如果T是一个数组types,则每个元素都进行了值初始化;
否则,该对象是零初始化的
在C中,对象从未被部分初始化 – 如果它们的任何部分被初始化,则整个对象(以及所有的子对象recursion地)被初始化。 如果没有提供明确的初始化程序,则将元素初始化为“适当types的零”。
你问题中的引用是指当整个对象的初始化完全被忽略的时候,而不是当一个子对象缺less一个初始化的时候。 例如,假设arr
具有自动存储持续时间,那么:
int arr[100] = { 123 };
将arr[0]
初始化为123
,将arr
每个其他元素初始化为0
。 而这个:
int arr[100];
使arr
每个元素arr
初始化。 这是后者的情况下,报价是参考。
最新的gcc版本也允许同时“部分”初始化和zeromem:
typedef struct{ int a,b,c; }T; T s = {0, .b=5};
结构成员现在将具有这些值: a=0, b=5, c=0
我没有关于其他编译器是否允许这样的信息:
如果variables是全局variables和静态variables,则在全局区域中分配初始化为零的二进制文件。 如果variables是本地variables,那么它将在堆栈中进行分配,编译器不会初始化堆栈中的内存(某些debugging版本可能会初始化,但是释放版本不会执行)
如果variables是在堆中分配的,编译器也不会初始化它。
// You can use something like this: typedef struct { ...; ...; } somestruct; // Declaration of struct somestruct st; // Initialising with 0. It does not depend on the size of the // structure and the number of elements in it. // memset() initialisation doesn't care if struct is static or dynamic. // but don't forget to use st instead &st to dynamic. memset(&st, 0, sizeof(somestruct));