C 为什么要在括号括起来的字符数组初始化中放置null终止符

C 为什么要在括号括起来的字符数组初始化中放置null终止符,c,C,我注意到,在许多书籍和在线教程中,当使用大括号括起来的列表初始化C字符串时,是这样做的: char string[100] = {'t', 'e', 's', 't', '\0' }; 难道所有未指定的值都不应该自动设置为0(即'\0')吗 我在GCC和MSVC的多个版本上对此进行了测试,所有值都确实设置为零,但我想知道在初始化时显式写入空终止符是否有特定的原因。当您显式指定字符数组的大小时,添加空终止符是绝对不必要的,并分配比字符串的有效负载部分所需的更多的字符。在这种情况下,标准要求用零初

我注意到,在许多书籍和在线教程中,当使用大括号括起来的列表初始化C字符串时,是这样做的:

char string[100] = {'t', 'e', 's', 't', '\0' };
难道所有未指定的值都不应该自动设置为0(即
'\0'
)吗


我在GCC和MSVC的多个版本上对此进行了测试,所有值都确实设置为零,但我想知道在初始化时显式写入空终止符是否有特定的原因。

当您显式指定字符数组的大小时,添加空终止符是绝对不必要的,并分配比字符串的有效负载部分所需的更多的字符。在这种情况下,标准要求用零初始化剩余的字符

唯一需要的时间是希望编译器自动确定以null结尾的数组的大小,即

char string[] = {'t', 'e', 's', 't', '\0' };
//         ^^

如果显式指定字符数组的大小,并且分配的字符数超过字符串有效负载部分所需的字符数,则绝对不需要添加null终止符。在这种情况下,标准要求用零初始化剩余的字符

唯一需要的时间是希望编译器自动确定以null结尾的数组的大小,即

char string[] = {'t', 'e', 's', 't', '\0' };
//         ^^
您是对的(请参阅“从括号内的列表初始化”)。但这是一种很好的做法,因为这样也可以毫无怨言地编译:

char string[4] = {'t', 'e', 's', 't'};
但是null不会终止任何内容,这会导致在将其用作字符串时出错。如果你说

char string[4] = {'t', 'e', 's', 't', '\0'};
编译器将知道这是一个错误,因为
'\0'
不适合

注意,它甚至比

char string[100] = "test";
出于同样的原因:

char string[4] = "test";
与第一个示例相同,而不是第二个

你说得对(请参阅“从括号内的列表初始化”)。但这是一种很好的做法,因为这样也可以毫无怨言地编译:

char string[4] = {'t', 'e', 's', 't'};
但是null不会终止任何内容,这会导致在将其用作字符串时出错。如果你说

char string[4] = {'t', 'e', 's', 't', '\0'};
编译器将知道这是一个错误,因为
'\0'
不适合

注意,它甚至比

char string[100] = "test";
出于同样的原因:

char string[4] = "test";

与第一个示例相同,而不是第二个

这是为了防止愚蠢的错误。如果要将字符解释为字符串,则需要第一个空字符

char string[4] = {'t', 'e', 's', 't'};
将愉快地编译,但不会以null结尾

char string[4] = {'t', 'e', 's', 't', '\0'};
将无法编译,这就是问题所在


通过显式指定空字符,编译器将验证数组是否足够大以达到预期目的。

这是为了防止愚蠢的错误。如果要将字符解释为字符串,则需要第一个空字符

char string[4] = {'t', 'e', 's', 't'};
将愉快地编译,但不会以null结尾

char string[4] = {'t', 'e', 's', 't', '\0'};
将无法编译,这就是问题所在


通过显式指定空字符,编译器将验证数组是否足够大以满足其预期目的。

我认为旧版本的C标准没有规定额外的元素应归零。提示:当您编写
char string[]={'t',e','s','t}?传递给printf()是否合适?@Jens这是不同的,因为它没有指定数组大小。@Barmar正是我的观点。这是防御性编程。您可以从一个集合切换到另一个集合,而不会产生不良影响。@Barmar:C90说(§6.5.7初始化):如果大括号内的列表中的初始值设定项少于集合的成员,则集合的其余部分应隐式初始化,与具有静态存储持续时间的对象相同。(聚合在此上下文中是“结构或数组”的意思。)我认为旧版本的C标准没有说额外的元素应该归零?传递给printf()是否合适?@Jens这是不同的,因为它没有指定数组大小。@Barmar正是我的观点。这是防御性编程。您可以从一个集合切换到另一个集合,而不会产生不良影响。@Barmar:C90说(§6.5.7初始化):如果大括号内的列表中的初始值设定项少于集合的成员,则集合的其余部分应隐式初始化,与具有静态存储持续时间的对象相同。(在此上下文中,聚合是指“结构或数组”。)