是否必须为字符数组的初始化提供'\0'?

Is it mandatory to give '\0' for initialization of character arrays?

请看代码:

#include <stdio.h>
#include <string.h>

int main(void)
{
    char name[10] = {'L','e','s','s','o','n','s'}; // did not add `[=10=]`
    char c;

    for (int i = 0; name[i] != '[=10=]'; i++)
    {
        c = name[i];
        printf("%c", c);
    }

    return 0;
}

我最后没有给[=11=],但还是有效

我的问题:[=11=]是在上面的情况下自动添加的吗?

编辑:在这些情况下会发生什么:

  1. char name[7] = {'L','e','s','s','o','n','s'};
  2. char name[8] = {'L','e','s','s','o','n','s'};

对于编辑问题,我深表歉意。

在 C 语言中,any 类型的部分初始化数组的其余部分为 0 初始化。所以,

int foo[5] = {1, 2, 3};

将用 {1, 2, 3, 0, 0} 初始化 foo。因此,当您不在末尾添加 '[=13=]' 时,不仅末尾将是 '[=13=]' (假设数组足够大以容纳它),而且数组的所有剩余元素都将是 '[ =13=]'.

如果您的数组不够大,无法容纳空终止符,则不会添加它,该值也不重要。读取数组末尾是未定义的行为,这可能导致段错误、垃圾数据或更糟的情况。

Is [=13=] added automatically in the above case?

是的。事实上,在您的 first 情况下(数组长度指定为 10),所有三个未 explicitly 初始化的数组元素将被默认初始化为零。

来自cppreference

All array elements that are not initialized explicitly are zero-initialized.

或者,来自 this Draft C11 Standard

6.7.9 Initialization
...
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.


对于你已经声明了char name[8]的情况也是如此(但是只会有一个添加'[=11=]',在那种情况下).

但是,对于 char name[7] = {'L','e','s','s','o','n','s'}; 的情况,您有 未定义的行为 - 紧跟在数组之后的内存位置的字节值可以是任何值(包括零)。

I did not give [=13=] at the end, but still it works.

那是因为你调用了未定义的行为。 UB 的结果是它似乎工作正常。

您不必明确添加 '[=11=]' 终止符如果您为它留出空间

您的原始代码是

char name[7] = {'L','e','s','s','o','n','s'}; // did not add `[=10=]`

没有终止的空间 '[=11=]'

根据 6.7.9 Initialization, paragraph 21 of the C11 standard:

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=]' 在您的字符串(字符数组)结束时添加。 如果您不想在某个字符后添加字符,则可以在该字符后明确添加 '[=10=]'

Is it mandatory to give '[=20=]' for initialization of character arrays?

不,不是。

一方面,char或任何其他字符类型的数组不包含任何值为 0 的元素是完全有效的。但是,这样的数组不包含string,并将指向它的指针(in)传递给任何依赖于您传递字符串的函数会导致未定义的行为。这有时可能表现为阵列已终止,但假设它会这样做是不安全的。

另一方面,如果您使用仅显式初始化其部分元素的初始化程序声明数组,则其他元素将被隐式初始化。对于 char 类型的元素,采用初始化为 0 的形式。请注意,此行为与初始化器相关联,而不是赋值。

适用于您的代码,然后,当数组 name 声明为维度 10 且初始化程序仅提供七个元素时,最后三个元素的初始值为零。相当于:

    char name[10] = {'L','e','s','s','o','n','s', 0, 0, 0};

...或者这个:

    char name[10] = {'L','e','s','s','o','n','s', '[=11=]', '[=11=]', '[=11=]'};

...甚至这个:

    char name[10] = "Lessons";

...还有其他可能性。

EDIT: What happens in this cases :

  1. char name[7] = {'L','e','s','s','o','n','s'};

所有数组元素都由给定的初始化程序显式初始化。数组内容不是空终止的,因此不构成字符串。任何将它们当作字符串使用的尝试都会导致未定义的行为。

  1. char name[8] = {'L','e','s','s','o','n','s'};

一个数组元素没有被显式初始化,所以它被隐式初始化为 0。如果意图是 name 应该有恰好正确数量的元素来包含指定的字符加上一个终止符,那么更清楚和安全地表示为

char name[] = "Lessons"; // Array dimension computed automatically

Is it mandatory to give '[=12=]' for initialization of character arrays?

不,一般不会。

然而,如果代码需要将初始化的字符数组视为 字符串 ,则需要某种 空字符 :显式或隐式.


char name[10] = {'L','e','s','s','o','n','s'}; 

My question : Is [=13=] added automatically in the above case?

是的。 没有部分初始化。 10 个元素中的 7 个被显式初始化。如果代码仅显式部分初始化一个对象,“所有未显式初始化的子对象都应隐式初始化,与具有静态存储持续时间的对象相同。” C17dr § 6.7.9 19

"如果一个具有静态或线程存储持续时间的对象没有被显式初始化,那么:
— 如果是指针类型,则初始化为空指针;
如果它有算术类型,它被初始化为(正数或无符号)零;
— 如果是聚合,则根据这些规则(递归地)初始化每个成员,并将任何填充初始化为零位;
— 如果是联合,第一个命名成员根据这些规则(递归)初始化,任何填充都初始化为零位; C17dr § 6.7.9 10


EDIT: What happens in this cases :
char name[7] = {'L','e','s','s','o','n','s'};
char name[8] = {'L','e','s','s','o','n','s'};

name[7] 如代码所示。 name[] 中不存在 空字符 因此 字符数组 一个 字符串.

name[8] 就好像 {'L','e','s','s','o','n','s', 0} 被编码了一样。因为它包含一个空字符name[]也是一个字符串


以下所有初始nameX[]为相同的值:

char name1[10] = {'L', 'e', 's', 's', 'o', 'n', 's'};
char name2[10] = {'L', 'e', 's', 's', 'o', 'n', 's', 0};
char name3[10] = {'L', 'e', 's', 's', 'o', 'n', 's', '[=11=]'};
char name4[10] = {'L', 'e', 's', 's', 'o', 'n', 's', 0, 0, 0};
char name5[10] = {[0] = 'L', [1] = 'e', [2] = 's', [3] = 's', [4] = 'o', [5] = 'n', [6] = 's'};
char name6[10] = {[1] = 'e', [2] = 's', [3] = 's', [4] = 'o', [5] = 'n', [6] = 's', [0] = 'L'};
char name7[10] = {[1] = 'e', [3] = 's', [2] = name7[3], [4] = 'o', [5] = 'n', [6] = 's', [0] = 'L'};
char name8[10] = "Lessons";
char name9[10] = "Lessons[=11=]";