【问题标题】:Variable holds the string "He", but "Hello World" gets printed变量保存字符串“He”,但打印“Hello World”
【发布时间】:2021-04-06 03:34:55
【问题描述】:
#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”!!

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

【问题讨论】:

  • 这是未定义的行为;您正在将“Hello World”写入数组末尾。 C 不关心数组的长度(它也不知道数组的长度),它只关心它在哪里找到一个超过结尾的空字节。
  • 哦!好吧...@Aplet123

标签: c string printf


【解决方案1】:

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

声明

 strcpy(c,"Hello World");

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

结果: undefined behavior.

相关,来自man page for strcpy()

[...] 字符串不能重叠,目标字符串 dest 必须足够大以接收副本。[...]

错误

如果 strcpy() 的目标字符串不够大,那么任何事情都可能发生。溢出固定长度的字符串缓冲区是一种最喜欢的破解技术,用于完全控制机器。每当程序读取或复制数据到缓冲区时,程序首先需要检查是否有足够的空间。如果您可以证明溢出是不可能的,这可能是不必要的,但要小心:程序可能会随着时间的推移而改变,其方式可能会使不可能成为可能。

【讨论】:

    【解决方案2】:

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

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

    第一条语句创建了两个char 内存位置,但字符串文字"Hello World" 至少需要12 个(包括\0 的空间)。在执行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 打算在您的程序稍后用于包含更大的字符串,则相应地调整其大小。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-14
      • 2018-03-11
      • 2014-01-10
      • 1970-01-01
      • 2020-05-02
      • 2015-05-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多