调用strcpy的结果与预期不同 #包括 #包括 int main() { 字符src[]=“123456”; strcpy(src,&src[1]); printf(“最终复制的字符串:%s\n”,src); }

调用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设计用于允许源

当我使用Visual Studio 6编译器时,它会给出预期的答案“
23456

当使用gcc 4.7.2编译时,该程序如何打印“
23556
”?

strcpy(src,&src[1])是未定义的行为:

C11§7.24.2.3
strcpy
功能
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
vs
memmove
问题。您在哪里找到这些信息?你怎么这么快就能找到他们?或者你写了自己的书: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