Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 有人能解释一下这两个发起者之间的区别吗?_C_Gcc_Gnu99 - Fatal编程技术网

C 有人能解释一下这两个发起者之间的区别吗?

C 有人能解释一下这两个发起者之间的区别吗?,c,gcc,gnu99,C,Gcc,Gnu99,我想知道是否有人能对以下两段代码之间的差异提供一个详细、简单的解释。根据以下定义: typedef struct { stuff; stuff_2; } variable_t; 以下两者之间的区别是什么: 变量\u t我的变量 variable\t my\u variable={} 如果我做了第一个,但从未完全初始化它,为什么编译器没有抛出错误 注意:我使用的是gcc-std=gnu99进行编译,因此第二个是有效的,并且最终是我遇到的问题的解决方案。我想知道为什么。当你宣布

我想知道是否有人能对以下两段代码之间的差异提供一个详细、简单的解释。根据以下定义:

typedef struct {
    stuff;
    stuff_2;
} variable_t;
以下两者之间的区别是什么:

  • 变量\u t我的变量
  • variable\t my\u variable={}
如果我做了第一个,但从未完全初始化它,为什么编译器没有抛出错误

注意:我使用的是
gcc-std=gnu99
进行编译,因此第二个是有效的,并且最终是我遇到的问题的解决方案。我想知道为什么。

当你宣布:

variable_t my_variable;           // a variable_t that is uninitialized

variable_t my_variable = {};      // a variable_t initialized with zeroes.
请注意,对于在文件范围内声明的变量,这实际上并不重要,因为数据通常在程序启动之前被清零

在堆栈上使用,第二行有效地用零填充my_变量。就好像有人打电话给:

memset(&variable,0,sizeof(variable))

这是因为在C中,可以使用
=
复制
结构

这是一个电脑一定会赢的小游戏

struct A { /*...*/ };

void main() 
{
   A a;  // random
   A b = {};
   if (memcmp(&a, &b, sizeof(A)) == 0)
   {
       printf("You win\n");
       return;
   }

   a = b;
   if (memcmp(&a, &b, sizeof(A)) == 0)
   {
       printf("I win\n");
   }
}

这有点取决于您将各自的变量定义放置在何处,而且似乎还取决于正在使用的编译器

自动存储持续时间

让我们讨论变量具有自动存储持续时间时的差异(如果将其放置在函数或块范围中,并且没有
static
关键字,则会出现这种情况):

(1) 表示没有显式初始化的变量定义。根据这个,它的值是不确定的:

如果未初始化具有自动存储持续时间的对象 显然,它的值是不确定的

(2) 是一个变量定义,通过不带指示符的初始值设定项列表进行显式初始化,即不通过名称将值与成员关联,但仅通过值的顺序(参见)

有趣的一段是,它指出,如果初始值设定项列表的条目数少于结构成员数,则根据静态存储持续时间的初始化规则初始化成员(即,到
0
NULL
,如下所述):

如果括号内的列表中的初始值设定项少于 是集合的元素或成员,剩余的 聚合的初始化应与 具有静态存储持续时间

因此,如果您编写
variable\t my\u variable={}
,那么所有成员都将初始化为
0
NULL

但是,正如aschepler在评论中提到的,声明初始值设定项列表不得为空(参见:

。。。初始值设定项必须是一个非空的大括号, 以逗号分隔的成员初始值设定项列表

因此,根据标准,C中的初始值设定项列表至少需要一个条目;在使用
-std=gnu99
在我的XCode8.3环境中测试它时,似乎支持空的初始化列表,但我知道这不是有效的引用。因此,为了安全且不依赖于特定的编译器扩展,您应该实际编写:

   variable_t my_variable = {0};  
静态存储持续时间

在文件范围内,变量定义将具有静态存储持续时间,然后应用其他规则(参见):

(10) 。。。如果具有静态或线程存储持续时间的对象是 未显式初始化,则:

  • 如果有指针类型,则初始化为空指针
  • 如果它有算术类型,则初始化为(正或无符号)零
  • 如果它是一个聚合,则根据这些规则(递归地)初始化每个成员,并将任何填充初始化为零位
  • 如果是联合,则根据这些规则(递归地)初始化第一个命名成员,并初始化任何填充 零位

(21)如果括号内列表中的初始值设定项少于集合中的元素或成员。。。聚合的其余部分应隐式初始化,与具有静态存储持续时间的对象相同

所以如果你写

#include <stdio.h>
variable_t my_variable;       // (1)
variable_t my_variable = {};  // (2)
#包括
变量\u t我的变量;//(1)
变量\u t my\u variable={};//(2)
然后(1)和(2)实际上产生相同的结果,因为对于未显式初始化的变量(1),第(10)段适用,而对于显式但为空的初始化变量(2),根据第(21)段,每个成员返回到(10)的初始化规则

同样,编译器可能不支持上面讨论的空初始化列表


希望它有帮助(因为输入了很多:-)

区别在于,第一个未初始化,第二个(到零)。编译器不会抛出错误,因为它假定您正在执行某些不便于更清楚地表达的特定操作。第二个(Gnu C接受)不是初始化为零,而是初始化为每个字段的默认值(好的,在C中可能是零)。似乎仅使用[C]无法回答此问题标记。@grzegorzzPetkowski很抱歉,我应该指定我使用的是gnu99编译器标志。添加了tagBetter,以便只使用
variable\t my_variable={0},可移植。IIRC,没有为gcc记录空大括号行为,它只是看起来有效。请注意,如果第一个大括号在文件范围内定义,则可能会初始化为全零,但如果它在块范围内定义,则不会。第二个在严格的标准C中是不合法的——它是一个C++符号(即使标准不允许,也有一些C编译器可能允许)。当然,在第一个代码> MeCMMP(A,……/代码)是UB的时候,使用未初始化的变量,如<代码> A <代码>(不是<代码>未签名的char <代码> >。
#include <stdio.h>
variable_t my_variable;       // (1)
variable_t my_variable = {};  // (2)