将字符串初始化为 {0, } 有什么作用?

What does initializing a string to {0, } do?

我见过这样的代码:

char str[1024] = {0, };

并怀疑它类似于这样做:

char str[1024];
str[0] = '[=11=]';

但是我在上面找不到任何东西,所以我不确定。

这是什么(叫做),它有什么作用?


免责声明:我知道以前可能有人问过这个问题并回答过这个问题,但是搜索 {0, } 是非常困难的。如果你能指出重复的问题,我会很乐意删除这个问题。

不,它们不一样。

此声明

char str[1024] = {0, };

将第一个元素初始化为给定值 0,所有其他元素都将被初始化,就好像它们具有静态存储一样,在本例中,值为 0。从句法上讲,这类似于使用

char str[1024] = {0};

引用 C11,第 6.7.9 章,第 21 页

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

并且,来自第 10 页(强调我的)

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static or thread storage duration is not initialized explicitly, then:

  • if it has pointer type, it is initialized to a null pointer;

  • if it has arithmetic type, it is initialized to (positive or unsigned) zero;

  • if it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;

  • if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;

另一方面

char str[1024];
str[0] = '[=12=]';

只初始化第一个元素,其余元素保持单元化状态,包含不确定的值。

{0, } 初始化器与更常见的 {0} 初始化器相同。 语法允许尾随逗号,但没有区别。

6.7.9--Initialization:

      initializer:
               assignment-expression
               { initializer-list }
               { initializer-list , }
      initializer-list:
               designationopt initializer
               initializer-list , designationopt initializer
      designation:
             designator-list =
      designator-list:
             designator
             designator-list designator
      designator:
             [ constant-expression ]
             . identifier

语义是 0,这在语法上是必需的,因为在语法上至少需要一个初始化列表项(这是一种任意要求:编译器经常支持空 {} 也) 递归地初始化第一个子对象 (6.7.9p17):

Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first named member of a union.148) In contrast, a designation causes the following initializer to begin initialization of the subobject described by the designator. Initialization then continues forward in order, beginning with the next subobject after that described by the designator.

如果整个对象具有静态存储持续时间 (6.7.9p19,6.7.9p21),则其余部分将初始化为 。这实际上意味着 0(与 memset(,0,) 一样,但需要注意的是填充不需要初始化并且 0 初始化的指针不一定是 "all-bits zero"。

据我所知,普通平台上的编译器(其中指针全为零)大部分情况下只是做它们在 memset(,0,).

上会做的事情

这个 "universal" 零初始化是有效的,因为第一个 0 将递归地命中一个标量类型(指针上的数字),它总是可以用 0 初始化器初始化。默认 "as-with-static-storage-duration" 然后初始化适用于其余部分。

尾随初始化逗号什么都不做的一个可能稍微更有趣的是:

int main()
{
    char one[]={0,}; //<the comma doesn't introduce another member
    _Static_assert(sizeof(one)==1,""); //holds
}