所以我好奇地阅读了一些C代码;假设我们有以下代码:
char text[10] = "";
C编译器在哪里放置空字符?
我可以想到3种可能的情况
'\0'
'\0'
问题是,根据任何一种情况,在执行'\0'
时是否有必要添加尾随strncpy
。如果是第2和第3种情况,那么这不是绝对必要的,而是一个好主意;如果它是案例1,那么这绝对是必要的。
这是什么?
答案 0 :(得分:5)
在初始化中,text
数组填充空字节(即选项#3)。
char text[10] = "";
相当于:
char text[10] = { '\0' };
因为text
的第一个元素被显式初始化为零,其余部分根据C11, Initialization 6.7.9, 21的要求隐式零初始化:
如果括号括起的列表中的初始值设定项少于此值 是聚合的元素或成员,或者是一个或多个字符 string literal用于初始化已知大小的数组 是数组中的元素,聚合的其余部分应为 隐式初始化与具有静态存储的对象相同 持续时间。
答案 1 :(得分:1)
引用N1256(大致为C99),因为语言之前或之后没有相关的变化:
6.7.8初始化
14字符数组的数组可以用字符串文字初始化,可选择用大括号括起来。字符串文字的连续字符(如果有空间或数组大小未知,则包括终止空字符)初始化数组的元素。
""
是由一个字符(其终止空字符)组成的字符串文字,此段落声明该字符用于初始化数组的元素,这意味着第一个字符初始化为零。这里没有任何内容说明数组的其余部分会发生什么,但有:
21如果括号括起的列表中的初始值设定项少于聚合的元素或成员,或者用于初始化已知大小的数组的字符串文字中的字符数少于数组中的元素,则余数为聚合的内容应与具有静态存储持续时间的对象隐式初始化。
此段落声明其余字符的初始化方式与静态存储持续时间相同,这意味着数组的其余部分也会初始化为零。
值得一提的是p14中的“如果有空间”:
在C中,char a[5] = "hello";
也是完全有效的,对于这种情况,你可能也想问一下编译器放置空字符的位置。这里的答案是:它没有。
答案 2 :(得分:0)
字符串文字""
在C中具有字符数组char[1]
的类型,在C ++中具有const char [1]
。
你可以通过以下方式想象它
在C
chat no_name[] = { '\0' };
或 在C ++中
const chat no_name[] = { '\0' };
当字符串文字用于初始化字符数组时,其所有字符都用作初始值设定项。所以对于这个宣言
char text[10] = "";
你其实已经
了char text[10] = { '\0' };
数组中没有相应初始值设定项的所有其他字符(第一个字符为text [0]除外)然后将它们初始化为0。
从C标准(6.7.9初始化)
14字符串数组可以用字符串初始化 文字或UTF-8字符串文字,可选择用大括号括起来。 字符串文字的连续字节(包括终止空值) 字符,如果有空间或数组的大小未知) 初始化数组的元素。
和
21如果括号括起的列表中的初始值设定项少于此值 是聚合的元素或成员,或者是一个或多个字符 string literal用于初始化已知大小的数组 是数组中的元素,聚合的其余部分应为 隐式初始化与具有静态存储的对象相同 持续时间
最后
10如果未初始化具有自动存储持续时间的对象 显然,它的价值是不确定的。如果一个对象有静态 或线程存储持续时间未明确初始化,然后:
- 如果它有指针类型,则将其初始化为空指针;
- 如果它有算术类型,则初始化为(正或无符号)零;
- 如果是聚合,则每个成员都被初始化(递归) 根据这些规则,任何填充都被初始化为零位;
- 如果是联合,则初始化第一个命名成员 (递归地)根据这些规则,并初始化任何填充 为零位;
类似的内容写在C ++标准中。
考虑到在C中你可以用以下方式编写
char text[5] = "Hello";
^^^
在这种情况下,字符数组将没有终止零,因为没有空间。 :)它和你定义的一样
char text[5] = { 'H', 'e', 'l', 'l', 'o' };