当我们不包括'\0';在C中字符串的末尾?

当我们不包括'\0';在C中字符串的末尾?,c,string,valgrind,null-terminated,C,String,Valgrind,Null Terminated,在C中,当我以这种方式初始化数组时: char full_name[] = { 't', 'o', 'a', 'n' }; 并用printf(“%s”,全名)打印 和valgrind一起运行我出错了 未初始化的值是通过堆栈分配创建的 为什么会发生这种情况?如果不在逗号分隔的括号内的初始值设定项列表的末尾提供'\0',从技术上讲,全名不是字符串,因为字符数组不是以null结尾的 只是想澄清一下,与初始值设定项是字符串文字不同,逗号分隔的列表不会自动计数并将终止的空字符放入数组中 因此,如

在C中,当我以这种方式初始化数组时:

char full_name[] = {
    't', 'o', 'a', 'n'
};
并用
printf(“%s”,全名)打印

和valgrind一起运行我出错了

未初始化的值是通过堆栈分配创建的


为什么会发生这种情况?

如果不在逗号分隔的括号内的初始值设定项列表的末尾提供
'\0'
,从技术上讲,
全名
不是字符串,因为
字符
数组不是以null结尾的

只是想澄清一下,与初始值设定项是字符串文字不同,逗号分隔的列表不会自动计数并将终止的空字符放入数组中

因此,如果定义为

char full_name[] = {
    't', 'o', 'a', 'n'
};
数组的大小为4,其中包含
't'
'o'
'a'
'n'

奥托,以防

char full_name[] = "toan";
全名的大小为5,其中包含
't'
'o'
'a'
'n'
'\0'

当您尝试将前一个数组与任何对字符串进行操作的函数(即,期望以null结尾的
char
数组)一起使用时,您将得到以下结果,因为大多数字符串函数在搜索null结尾符时都会越界

在您的特定示例中,对于带有
printf()
%s
格式说明符,引用
C11
标准,第§7.21.6.1章,
fprintf()
函数描述(重点)

s

如果不存在
l
长度修饰符,则参数应为指向初始值的指针 字符类型为.280)的数组的元素 写入(但不包括)终止空字符。如果 指定了精度,写入的字节数不超过该字节数如果 精度未规定或大于阵列尺寸时,阵列应 包含空字符。


这意味着,
printf()
将查找空终止符来标记/理解数组的结尾。在您的示例中,缺少空终止符将导致
printf()
超出分配的内存(
full\u name[3]
)并访问绑定外内存(
full\u name[4]
),这将导致UB。

如果您没有在逗号分隔的括号内初始值设定项列表的末尾提供
'\0'
,从技术上讲,
full\u name
不是字符串,因为
char
数组不是以null结尾的

只是想澄清一下,与初始值设定项是字符串文字不同,逗号分隔的列表不会自动计数并将终止的空字符放入数组中

因此,如果定义为

char full_name[] = {
    't', 'o', 'a', 'n'
};
数组的大小为4,其中包含
't'
'o'
'a'
'n'

奥托,以防

char full_name[] = "toan";
全名的大小为5,其中包含
't'
'o'
'a'
'n'
'\0'

当您尝试将前一个数组与任何对字符串进行操作的函数(即,期望以null结尾的
char
数组)一起使用时,您将得到以下结果,因为大多数字符串函数在搜索null结尾符时都会越界

在您的特定示例中,对于带有
printf()
%s
格式说明符,引用
C11
标准,第§7.21.6.1章,
fprintf()
函数描述(重点)

s

如果不存在
l
长度修饰符,则参数应为指向初始值的指针 字符类型为.280)的数组的元素 写入(但不包括)终止空字符。如果 指定了精度,写入的字节数不超过该字节数如果 精度未规定或大于阵列尺寸时,阵列应 包含空字符。


这意味着,
printf()
将查找空终止符来标记/理解数组的结尾。在您的示例中,缺少空终止符将导致
printf()
超出分配的内存(
full\u name[3]
)并访问绑定外内存(
full\u name[4]
),这将导致UB。

,因为
%s
格式说明符需要以空结尾的字符串,代码的结果行为未定义。您的程序被认为是格式不正确的,可以产生任何输出、不产生输出、崩溃等等。简而言之,不要那样做

这并不是说所有字符数组都必须以null结尾:该规则仅适用于用作C字符串的字符数组,例如传递给
%s
格式说明符上的
printf
,或传递给标准C库的
strlen
或其他字符串函数

如果打算将
char
数组用于其他用途,则不需要以null结尾。例如,此用途已完全定义:

char full_name[] = {
    't', 'o', 'a', 'n'
};
for (size_t i = 0 ; i != sizeof(full_name) ; i++) {
    printf("%c", full_name[i]);
}

由于
%s
格式说明符需要以null结尾的字符串,因此代码的结果行为未定义。您的程序被认为是格式不正确的,可以产生任何输出、不产生输出、崩溃等等。简而言之,不要那样做

这并不是说所有字符数组都必须以null结尾:该规则仅适用于用作C字符串的字符数组,例如传递给
%s
格式说明符上的
printf
,或传递给标准C库的
strlen
或其他字符串函数

如果打算将
char
数组用于其他用途,则不需要以null结尾。例如,thi