这是我的C代码
#include <stdio.h>
int main()
{
char c[3] = "abc";
char a[6] = "Shamal";
printf("%s\n\n", c);
printf("%s\n\n", a);
return 0;
}
这里的输出是
abcW?
Shamal
6个字符的字符串正确显示字符串,3个字符的字符串显示W?在代码的最后。
我知道我们需要把空字符&#39; \ 0&#39;终止字符串。但是这里两个字符串都没有空字符但只有一个正常工作。这是什么原因?
答案 0 :(得分:2)
正如上面的评论所说,undefined是未定义的,但对你的问题的确切答案是,它偶然发生在第一个字符串之后的内存字节不是0,但是&#39; W&#39;然后&#39;?&#39;然后是0,终止一个字符串。
对于第二个字符串,碰巧字符串后面的一个字节意外地为0,因此它被正确打印。
尝试重新排序初始化并查看输出是否会发生变化(最有可能)。
答案 1 :(得分:2)
每当你写char c[4] = "abc";
或char c[] = "abc";
之类的内容时,字符串abc
都会被存储内存(并且你无法更改此字符串)并自动附加\0
。在这两种情况下,您都没有为终止NUL
字符分配空间。
对于char a[6] = "Shamal";
,如果您要遍历字符并按索引0
通过5
打印它们,您将收到字符串。
现在,如果您仔细注意,您已为六个字符仅留出空间并且\0
没有空间。 \0
可能会写入您不拥有的空间,即l
之后。在这个阶段,你已经超出了你认为足够的缓冲空间。这本身足以导致UB。当您要求printf
打印出您的字符串时,会出现另一个问题。 printf
会继续打印,直到找到\0
为止。一旦你调用UB,就不知道将会发生什么。
检查this以获取其他说明。
答案 2 :(得分:1)
继续我的评论,您只是没有提供足够的空间来在初始化中创建字符字符串。以下内容为 nul-terminatedating 字符创建了字符数组 ,没有空间:
char c[3] = "abc";
char a[6] = "Shamal";
编译期间不会收到任何警告,因为初始化是字符数组的有效初始化 - 而不是字符串。
例如,char c[3] = "abc";
会在内存中产生以下连续字节:
| a | b | c |
这是一个由3个元素组成的有效字符数组,每个元素都可以编入索引为c[0], c[1], c[2]
。但是,要将c
用作字符串,c
需要以下内存中的4个连续字节:
| a | b | c |\0|
要纠正问题并允许编译器在初始化过程中包含 nul-terminatedating 字符,请不要为数组提供大小,编译器会自动调整数组的大小以提供包含 nul-character 所需的额外空间,例如
char c[] = "abc";
char a[] = "Shamal";
或者(更容易出错),为自己提供 nul-character 的空间,例如
char c[4] = "abc";
char a[7] = "Shamal";
两者都会导致c
和a
包含 nul-terminatedating 字符,允许每个字符在代码中用作字符串。