strcpy 中,遇到内存重叠,为什么结果是这样?

2022-01-02 01:31:14 +08:00
 amiwrong123
#include <stdio.h>
#include <string.h>

int main()
{
	char s[10] = "hello"; 
	printf("%s\n", strcpy(s, s + 1));
	printf("%s\n", s);

	return 0;
}

打印结果是:

ello
ello

这个我理解,把ello\0往前复制了。

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

int main()
{
	char s[10] = "hello"; 
	printf("%s\n", strcpy(s + 1, s));
	printf("%s\n", s);

	return 0;
}

打印结果却是:

helll
hhelll

这个hhelll我就不理解了。不应该是hhello

本来想试一下 strcpy 的行为,自己写个实现。但现在它的行为我不理解了。

vs2019 试的,需要按照 https://blog.csdn.net/oguro/article/details/52685662 添加宏才能运行。

1922 次点击
所在节点    程序员
10 条回复
fishCatcher
2022-01-02 01:44:02 +08:00
这是个未定义行为,所以你怎么实现都可以,
yulon
2022-01-02 01:51:11 +08:00
你要问这种有冲突的问题,当然只能得到有冲突的结果。

strcpy 作为一个拷贝函数,自然是不会分配额外内存,不然直接给你返回一个新字符串不就完了。

那么在有限的内存里,它有可能用算法解决内存重叠,也有可能解决不了。

猜测你是 32 位程序,内部实现是以机器字为单位来拷贝,也就是 4 个字节,拷贝一次之后,第 5 个字节已经变了,自然就多出来一个 l 。

建议别浪费时间在这种问题上,而且写出这种程序非常恐怖。
wudicgi
2022-01-02 02:30:06 +08:00
yulon 已经把需要说的都说了,极有可能就是按 4 字节处理出来的结果,因为 s 在栈里分配,地址会是 4 字节对齐的
如果有兴趣可以试试 s[10] = "_hello" 时 strcpy(s + 2, s + 1) 的情况,结果应该不一样
不过其实深究这个意义不大,首先考虑把 strcpy() 换成 strncpy(), strncpy_s() 之类的函数,其次必要时自己加额外判断

另外,看到你想自己写个 strcpy() 的实现,
如果是 for 循环简单的逐字节复制,怕是这时 strcpy() 会直接运行到访问地址无读写权限的情况,
把从 s 起始位置开始的所有的能读写的字节都改成 'h'

标准库的实现会不一样,有的库可能先 strlen() 算好长度再调用 memcpy(), 这样不会有一直处理下去的问题,
但具体结果如何得看具体代码了,一般会有不少优化的,毕竟 memcpy() 很常用
wevsty
2022-01-02 02:58:59 +08:00
不要纠结这些标准库函数内部怎么实现的,看你换个编译器,甚至换个版本就会变了。
dangyuluo
2022-01-02 03:21:27 +08:00
> The behavior is undefined if the strings overlap.
2i2Re2PLMaDnghL
2022-01-02 04:49:05 +08:00
未定义行为,电脑直接爆炸也是逻辑上允许的。
直接按照标准去写就行,标准大于约定。
thedrwu
2022-01-02 06:12:41 +08:00
未定义的。你的 code reviewer 会把这种情况打回来重写。
kokutou
2022-01-02 09:35:02 +08:00
不要研究未定义行为。。。
除非你是搞编译器之类底层的。。。
codehz
2022-01-02 10:04:54 +08:00
(这一系列函数中,只有 memmove 是保证重叠的时候正确的)
agagega
2022-01-02 15:51:06 +08:00
只有 memmove 可以重叠

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/825731

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX