变量保存字符串 "He",但 "Hello World" 被打印

Variable holds the string "He", but "Hello World" gets printed

#include<stdio.h>
#include<string.h>

main()
{
 char c[2];
      strcpy(c,"Hello World");
      printf("%s",c);
}

在上面的代码中,我初始化了一个只能容纳两个字符的字符数组。那么,上面代码的输出一定是“He”。但是,我发现输出是“Hello World”。这怎么可能?

调试这个程序发现,直到执行printf语句,c的值确实(如预期)为“He”。但是在执行 printf 之后,输出屏幕上打印了全文“Hello World”!

有趣的是 c 包含字符串“He”,但是当我们打印出 c 时,它会打印“Hello World”!!

谁能解释一下这是怎么回事?

以下语句通过尝试写入 运行 程序不拥有的内存来调用 undefined behavior (UB)。

char c[2];
strcpy(c,"Hello World");

第一个语句创建了两个 char 内存位置,但字符串文字 "Hello World" 至少需要 12 个(包括 [=15=] 的空间)。执行 strcpy(...) 任何事情都可能发生,甚至看起来有效,但如前所述,它正在调用 UB。

char 数组的预期用途声明足够的空间是必不可少的,可以通过多种方式完成,例如,以下任一方法都可以:

 char c[] = {"Hello World"};//let compiler do the work of determining size needed
 printf("%s", c);

或:

 char c[12] = {0};//provide minimum of length of string + 1 for null termination.

 strcpy(c,"Hello World");
 printf("%s", c);

但是,如果 c 打算用于稍后在您的程序中包含更大的字符串,则相应地增大它的大小。

这是 undefined behavior,您正在尝试访问在您的程序上下文中无效的内存。

声明

 strcpy(c,"Hello World");

尝试将较大的源复制到较小的目标,并且由于 strcpy() 不对源长度和提供的目标缓冲区的长度进行任何检查,因此在尝试复制时,它会访问超过未分配给您的程序的有效内存和访问内存。

结果: undefined behavior.

相关,来自man page for strcpy()

[...] The strings may not overlap, and the destination string dest must be large enough to receive the copy.[...]

Bugs

If the destination string of a strcpy() is not large enough, then anything might happen. Overflowing fixed-length string buffers is a favorite cracker technique for taking complete control of the machine. Any time a program reads or copies data into a buffer, the program first needs to check that there's enough space. This may be unnecessary if you can show that overflow is impossible, but be careful: programs can get changed over time, in ways that may make the impossible possible.