C编程中对字符串的困惑

0 c printf c-strings string-literals array-initialization

所以我正在学习使用编译器Dev C++编程c.问题1:

#include <stdio.h> 
#include <conio.h> //for the getch() function
#include <string.h> 

int main(void) 
{ 
    char line[3]; 
    strcpy(line, "Hello world"); 
    printf("%s", line); 
    getch(); 
} 
Run Code Online (Sandbox Code Playgroud)

输出:Hello world

为什么当我声明我的字符串只能容纳3个字符时,它会显示所有"Hello world"?

问题2:

char line[3] = "Hello world"; 
printf("%s", line); 
Run Code Online (Sandbox Code Playgroud)

输出:Hel

为什么显示"Hel"?它不应该只显示"He",因为行[0] = H,行[1] = e和行[2] ='\ 0'?%s通过搜索'\ 0'来工作?

请帮我理解真正发生的事情.谢谢!

leg*_*s2k 11

请帮我理解真正发生的事情.

未定义的行为!

当你这样做时,你有一个缓冲区溢出:

char line[3]; 
strcpy(line, "Hello world"); 
Run Code Online (Sandbox Code Playgroud)

为什么当我声明我的字符串只能容纳3个字符时,它会显示所有"Hello world"?

您复制的数量超过了已分配数组的大小.这是未定义的行为,因此任何输出都是可能的,包括但不限于,调用阿姨Tilda,格式化您的硬盘等.:) 请参阅此处了解更多信息.


char line[3] = "Hello world"; 
printf("%s", line); 
Run Code Online (Sandbox Code Playgroud)

在这里你有一个缓冲读取!请参阅alk的答案,了解为什么只复制3个字符line.

为什么显示"Hel"?不应只显示"他"

不,它可以显示任何内容,因为未定义的行为.看看我的机器输出结果:

Hel☻

这是未定义的行为,因为printf期望你有一个以null结尾的字符串,是的,但这并不意味着你可以访问超出数组的大小,即你在内存中有这样的数组

                 [0] [1] [2]
-----------------------------------------------
. . . ? | ? | ? | H | e | l | ? | ? | ? | . . .
-----------------------------------------------
                <-- line --->
Run Code Online (Sandbox Code Playgroud)

上面写为█的任何东西都是未知的值,不是在你的权力之下,因此访问它们是不确定的.但是,%sprintf期望一个以null结尾的字符串,因此,在您的命令下,它读取超出允许的范围(允许的只是三个元素直到l).在我的情况下\0,l(笑脸)之后出现了一个元素,而在你的情况下,它刚刚l出现正确,但只有运气,它可能会出现1000个元素.


如果您确实要打印char非空终止的数组,只能达到允许的限制,您可以执行其中一个而不会遇到任何未定义的行为.

printf("%.3s", line);       // length specified at compile-time

printf("%.*s", 3, line);    // length fed at run-time
Run Code Online (Sandbox Code Playgroud)

请参阅此处获取更多信息.

  • 我想你可能想要提到UB不仅意味着_it可以显示任何东西_而且它可以做很多事情,例如什么都不显示,崩溃,呕吐彩虹等. (5认同)