【问题标题】:strcpy function not working properlystrcpy 函数无法正常工作
【发布时间】:2017-12-15 22:05:58
【问题描述】:

请考虑下面的代码。

#include<stdio.h>
#include<string.h>
void main()
{
    char a[6], b[6];

    strcpy(a,"rajeev");
    printf("print A:");
    for(int i=0;i<strlen(a);i++)
    {
         printf("%c",a[i]);
    }

    strcpy(b,a);
    printf("print B:");
    for(int i=0;i<strlen(b);i++)
    {
        printf("%c",b[i]);
    }

    printf("trying to print A again");
    for(int i=0;i<strlen(a);i++)
    {
        printf("%c",a[i]);
    }

运行此程序时,在“尝试再次打印 A”部分不打印任何内容,strlen(a) 将为 0。这意味着源数组将为空。

你能帮我理解这背后的现象吗? 但是,将a[6] 的声明更改为char* a=malloc(6) 可以正常工作。

【问题讨论】:

  • 数组在这里是字符串的一个元素。
  • strlen(a) 很可能是 UB..
  • 如果您尝试使用"raj" 而不是"rajeev",它会起作用。这是因为您没有计算空终止符。
  • strcpy(a,"rajeev"); 是 UB,因为它正在访问分配的内存。

标签: c arrays string strcpy strlen


【解决方案1】:

字符串文字"rajeev" 的类型为char[7]。也就是说,它具有静态存储持续时间,并存储为像

一样初始化的数组
char unnamed[] = { 'r', 'a', 'j', 'e', 'e', 'v', '\0' };

因此,如果您要使用函数strcpy 将其内容复制为字符串,则需要在目标数组中提供足够的内存。例如

char a[7], b[7];

strcpy(a,"rajeev");
printf("print A:");
for ( size_t i = 0, n = strlen( a ); i < n; i++ )
{
     printf("%c",a[i]);
}

//... and so on

考虑到函数strlen 对字符进行计数,直到遇到终止零。所以如果一个字符数组不包含这个字符,那么函数的行为是未定义的。

【讨论】:

    【解决方案2】:

    您的数组不足以容纳您要存储的字符串。

    C 中的字符串被定义为 以空字符结尾的字符序列,这意味着正确的字符串末尾有一个空字节。

    您的数组可以容纳 6 个字节,但您的字符串 "rajeev" 需要 7 个字节(6 个用于字母,1 个用于末尾的隐式空字节。因此,您写入数组的末尾。写在外面数组的边界调用undefined behavior

    在您动态分配内存的情况下,您将再次调用未定义的行为。在这种情况下,它似乎可以正常工作。这是未定义行为的表现方式之一。

    要解决此问题,您的数组至少需要 7 个元素:

    char a[7], b[7];
    

    【讨论】:

      【解决方案3】:

      a & b 太小了,因为 a 就在 b 之后,它的第一个字节在 strcpy 执行后为零。

      malloc 起作用了,因为这块内存是在内存中的另一个位置分配的。但这只是偶然的,因为您写入的内存比分配的多。

      对未以某种方式分配的内存的任何访问都是非法的,它是一个 UB。

      【讨论】:

      • 您正在做某事,但 ab 的顺序(在堆栈上,如果有堆栈)是未定义的。
      • 我从程序结果中猜到了:)来解释为什么a的第一个字节变成0。
      • 最好专注于改进代码而不是试图解释未定义的行为。你能把你的“评论”转换成正确的答案吗?
      • 对不起,这是评论,不是回答,应该提供解决方案,而不是猜测UB。
      • 好吧,如果您关心提供有用的答案,您也应该解决 OP 关于为什么 malloc 有效的问题。
      【解决方案4】:

      您定义的数组char a[6], b[6] 没有足够的空间来存储您要存储的字符串。

      请记住,C 中的每个数组末尾都有一个空字节 \0

      你可以通过给数组足够的空间来修复它:

      char a[7], b[7];
      

      【讨论】:

      • 空字节是\0 不是"/0"
      • 是的。我的坏 :D。更新!感谢您的信息
      猜你喜欢
      • 1970-01-01
      • 2014-04-06
      • 2013-03-30
      • 2013-03-27
      • 2012-08-15
      • 2013-11-05
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      相关资源
      最近更新 更多