调用strcpy的结果与预期不同 #包括 #包括 int main() { 字符src[]=“123456”; strcpy(src,&src[1]); printf(“最终复制的字符串:%s\n”,src); }
当我使用Visual Studio 6编译器时,它会给出预期的答案“调用strcpy的结果与预期不同 #包括 #包括 int main() { 字符src[]=“123456”; strcpy(src,&src[1]); printf(“最终复制的字符串:%s\n”,src); },c,strcpy,C,Strcpy,当我使用Visual Studio 6编译器时,它会给出预期的答案“23456” 当使用gcc 4.7.2编译时,该程序如何打印“23556”?strcpy(src,&src[1])是未定义的行为: C11§7.24.2.3strcpy功能 strcpy函数复制由s2指向的字符串(包括终止null 字符)插入到由s1指向的数组中如果复制发生在 重叠,行为未定义。 顺便说一下,memcpy与之类似(但不是memmove)。请参阅。这是未定义的行为。改用memmove功能memmove设计用于允许源
23456
”
当使用gcc 4.7.2编译时,该程序如何打印“23556
”?strcpy(src,&src[1])代码>是未定义的行为:
C11§7.24.2.3strcpy
功能
strcpy
函数复制由s2
指向的字符串(包括终止null
字符)插入到由s1
指向的数组中如果复制发生在
重叠,行为未定义。
顺便说一下,memcpy
与之类似(但不是memmove
)。请参阅。这是未定义的行为。改用memmove
功能memmove
设计用于允许源缓冲区和目标缓冲区重叠
#include <stdio.h>
#include <string.h>
int main()
{
char src[]="123456";
strcpy(src, &src[1]);
printf("Final copied string : %s\n", src);
}
来自ISO/IEC 9899:TC3(c99)
7.21.2.3 strcpy功能
概要
一,
#包括
char*strncpy(char*restrict s1,
const char*restrict s2,
size\u t n)代码>
描述
2 strcpy函数复制s2指向的字符串(包括终止null)
字符)插入s1指向的数组中如果复制发生在
重叠,行为未定义。
因此,您所做的只是未定义的行为;)
也可参见附件J.2
说明未定义行为的情况,并说明如何防止:
在以下情况下,该行为未定义:
[……]
-试图使用库将对象复制到重叠对象
功能,明确允许的功能除外(如memmove)(第7条)
未定义的行为,请使用memmov()而不是。您是如何得出这样一个事实的:它在哪里重叠&Src[1]=“23456”对!?!那么重叠在哪里呢?@PeterMiehle是的,memmov加上一个额外的e
src
衰减为指向数组src
的第一个元素的指针&src[1]
是指向数组第二个元素的指针。由于源字符串的长度不是0,它们显然是重叠的。这意味着我必须从另一个字符串“char dest[]=“123456”
”复制,然后执行“strcpy(src,&dest[1]);
”嗯。。。似乎类似于memcpy
vsmemmove
问题。您在哪里找到这些信息?你怎么这么快就能找到他们?或者你写了自己的书:D?@Rizier123我附近有一份C标准草案,如果这是你要问的:)。请参阅。@Rizier123:在我的系统上,glibc手册页(man 3 strcpy
)中描述了它:字符串不能重叠。@Blood HaZaRd:这是未定义的行为,实现可以随心所欲地执行。是的,内存重叠。而不是外观笨拙的&src[1]
,为了清楚起见,您可以使用src+1
。@Jongware您是对的,但我故意让它与原始问题中的相同。
memmove(src, &src[1], strlen(&src[1]) + 1) ; // + 1 for copying the terminating zero