这link表示"当自动数组或结构具有部分初始值设定项时,余数初始化为0"。我决定尝试我读到的内容并编写以下代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
//int arr[3] = {2}; // line no. 7
struct s {
int si;
int sj;
};
struct s myStruct;
myStruct.si = 9;
printf("%d\n", myStruct.sj);
}
我不明白为什么4096
(我相信是某些&#34;垃圾&#34;值)在我发表评论line no. 7
时会打印出来0
当我取消注释line no. 7
时。我不认为arr
声明与main()
的激活记录(或更确切地说myStruct
)有关,应该是这样的(如果我们有{ {1}}取消评论):
line no. 7
有人可以解释我在这里缺少的东西吗?
答案 0 :(得分:51)
执行此操作时:
struct s myStruct;
myStruct.si = 9;
您尚未初始化 myStruct
。您在没有初始化程序的情况下将其声明为,然后运行语句以设置一个字段。
因为变量未初始化,其内容未定义,读取内容为undefined behavior。这意味着看似无关的更改可以修改此行为。在您的示例中添加了一个额外的变量发生以使myStruct.sj
为0,但不保证会出现这种情况。
要初始化变量,您必须在定义时为其赋值:
struct s myStuct = { 9 };
如果你这样做,那么你会看到myStruct.sj
的内容设置为0.这是根据the C standard的第6.7.8节保证的(具体针对这种情况突出显示) :
10如果没有自动存储持续时间的对象 显式初始化,其值是不确定的。 如果是对象 具有静态存储持续时间的未初始化 显式,然后:
- 如果它有指针类型,则将其初始化为null 指针;
- 如果它有算术类型,则将其初始化为(正数或 无符号)零;
- 如果是聚合,则会初始化每个成员 (递归地)根据这些规则;
- 如果它是一个联盟,第一个 命名成员根据这些规则初始化(递归)。
...
21 如果括号括起的列表中的初始值设定项少于此值 是聚合的元素或成员,或者是一个或更少的字符 string literal用于初始化已知大小的数组 是数组中的元素,聚合的其余部分 应该与具有静态的对象隐式初始化 储存期限。
答案 1 :(得分:15)
在你的情况下,
myStruct.si = 9;
是 assignment 声明,不是 initialization 。在这种情况下,结构变量(和相应的变量)是未初始化的。因此,您最终会读取未初始化变量sj
的值,从而导致undefined behavior。
你可以尝试
struct s myStruct = {9};
查看隐式初始化。
答案 2 :(得分:11)
这不是初始化程序 - 您的结构未初始化,然后您只分配si
。 sj
仍未初始化。
这本书指的是这种代码:
struct s myStruct = {9};
...其中sj
保证为0。
答案 3 :(得分:2)
这基本上是一个 - 或多或少完整的例子,用于其他人已经给出的伟大答案。
#include<stdio.h>
struct{
int a;
int b;
}obj1={.a=0}; //Partial initialization
typedef struct struct_B{
int a;
int b;
}struct_B;
int main(void)
{
printf("obj1.b : %d\n",obj1.b);
struct_B obj2={.b=1,.a=0,0}; // b's first value is overridden here as 0 immediately follows a
printf("obj2.b : %d\n",obj2.b);
struct_B obj3={0}; //Partial initialization, here the '0' value is meant for a as it comes first in the declaration
printf("obj3.b : %d\n",obj3.b);
struct_B obj4={.a=0}; //Partial initialization
printf("obj4.b : %d\n",obj4.b);
return 0;
}
<强>输出:强>
obj1.b : 0
obj2.b : 0
obj3.b : 0
obj4.b : 0