#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 添加宏才能运行。
1
fishCatcher 2022-01-02 01:44:02 +08:00 via iPhone
这是个未定义行为,所以你怎么实现都可以,
|
2
yulon 2022-01-02 01:51:11 +08:00 3
你要问这种有冲突的问题,当然只能得到有冲突的结果。
strcpy 作为一个拷贝函数,自然是不会分配额外内存,不然直接给你返回一个新字符串不就完了。 那么在有限的内存里,它有可能用算法解决内存重叠,也有可能解决不了。 猜测你是 32 位程序,内部实现是以机器字为单位来拷贝,也就是 4 个字节,拷贝一次之后,第 5 个字节已经变了,自然就多出来一个 l 。 建议别浪费时间在这种问题上,而且写出这种程序非常恐怖。 |
3
wudicgi 2022-01-02 02:30:06 +08:00 1
yulon 已经把需要说的都说了,极有可能就是按 4 字节处理出来的结果,因为 s 在栈里分配,地址会是 4 字节对齐的
如果有兴趣可以试试 s[10] = "_hello" 时 strcpy(s + 2, s + 1) 的情况,结果应该不一样 不过其实深究这个意义不大,首先考虑把 strcpy() 换成 strncpy(), strncpy_s() 之类的函数,其次必要时自己加额外判断 另外,看到你想自己写个 strcpy() 的实现, 如果是 for 循环简单的逐字节复制,怕是这时 strcpy() 会直接运行到访问地址无读写权限的情况, 把从 s 起始位置开始的所有的能读写的字节都改成 'h' 标准库的实现会不一样,有的库可能先 strlen() 算好长度再调用 memcpy(), 这样不会有一直处理下去的问题, 但具体结果如何得看具体代码了,一般会有不少优化的,毕竟 memcpy() 很常用 |
4
wevsty 2022-01-02 02:58:59 +08:00
不要纠结这些标准库函数内部怎么实现的,看你换个编译器,甚至换个版本就会变了。
|
5
dangyuluo 2022-01-02 03:21:27 +08:00
> The behavior is undefined if the strings overlap.
|
6
2i2Re2PLMaDnghL 2022-01-02 04:49:05 +08:00 3
未定义行为,电脑直接爆炸也是逻辑上允许的。
直接按照标准去写就行,标准大于约定。 |
7
thedrwu 2022-01-02 06:12:41 +08:00 via Android
未定义的。你的 code reviewer 会把这种情况打回来重写。
|
8
kokutou 2022-01-02 09:35:02 +08:00 via Android
不要研究未定义行为。。。
除非你是搞编译器之类底层的。。。 |
9
codehz 2022-01-02 10:04:54 +08:00 via Android 1
(这一系列函数中,只有 memmove 是保证重叠的时候正确的)
|
10
agagega 2022-01-02 15:51:06 +08:00 via iPhone
只有 memmove 可以重叠
|