请帮助我了解真正发生的事情。
未定义的行为!
当你这样做时,你有一个缓冲区溢出:
char line[3];
strcpy(line, "Hello world");
为什么当我声明我的字符串只包含 3 个字符时它显示所有“Hello world”?
您复制的数量超过了分配数组的大小。这是未定义的行为,因此任何输出都是可能的,包括但不限于打电话给 Tilda 姨妈、格式化硬盘等 :)更多信息请参见此处。
char line[3] = "Hello world";
printf("%s", line);
在这里,您有一个缓冲区过度读取!请参阅alk 的回答,了解为什么只有 3 个字符会被复制到line
.
为什么它显示“Hel”?它不应该只显示“他”吗
不,它可以显示任何东西,同样是因为未定义的行为。看看我在我的机器上得到了什么输出:
嘿☻</p>
这是未定义的行为,因为printf
希望您有一个以 null 结尾的字符串,是的,但这并不意味着您可以访问超出数组大小的内容,即您在内存中有一个这样的数组
[0] [1] [2]
-----------------------------------------------
. . . █ | █ | █ | H | e | l | █ | █ | █ | . . .
-----------------------------------------------
<-- line --->
上面写成 █ 的任何东西都是未知值,不在你的权力范围内,因此访问它们是未定义的。但是,%s
inprintf
需要一个以 null 结尾的字符串,因此,根据您的命令,它读取的内容超出了允许的范围(允许的内容只有三个元素 until l
)。在我的情况下,在(笑脸)\0
之后出现了一个元素l
,而在你的情况下,它只是在l
出现正确但仅靠运气之后,它很可能会在 1000 个元素之后出现。
如果您真的想打印char
不是以空值结尾的数组,只打印到允许的限制,您可以执行其中之一,而不会遇到任何未定义的行为。
printf("%.3s", line); // length specified at compile-time
printf("%.*s", 3, line); // length fed at run-time
请参阅此处了解更多信息。