在C标准库中,函数strcpy、memcpy以及memmove都可以完成复制操作,它们是怎么实现的?为什么要有三个复制函数呢?
下面以GNU的glibc来分析三者的实现和区别。
strcpy
函数strcpy()由glibc/string/strcpy.c实现,用于执行字符串的复制操作:
1 | /* Copy SRC to DEST. */ |
strcpy()内部直接调用了memcpy()。strlen (src) + 1目的在于,加上末尾的结束符'\0'。
memcpy
函数memcpy()由glibc/string/memcpy.c实现,其按照从前往后的顺序依次复制,无法正确处理重叠问题:
1 | void * |
1.条件判断len >= OP_T_THRES中的OP_T_THRES定义在glibc/sysdeps/generic/memcopy.c中:
1 | /* Type to use for aligned memory operations. |
2.宏BYTE_COPY_FWD定义同样在glibc/sysdeps/generic/memcopy.c中,用于执行从前往后逐字节的复制操作:
1 | /* Copy exactly NBYTES bytes from SRC_BP to DST_BP, |
其中,do {} while(0)的目的在于,确保预编译时,宏定义中的语句被正确替换。
3.宏PAGE_COPY_FWD_MAYBE的定义如下:
1 |
|
memmove
函数memmove()定义在glibc/string/memmove.c中。
当目标区域和源区域不存在重叠时,其直接调用了函数memcpy(),按照从前往后的顺序依次复制;
而当目标区域和源区域存在重叠问题时,其按照从后往前的顺序依次复制:
1 | void * |
区别和联系
| 函数 | 描述 | 复制方法 |
|---|---|---|
| strcpy() | 复制字符串 | 从前往后依次复制,内部调用了函数memcpy() |
| memcpy() | 复制内存区域 | 从前往后依次复制 |
| memmove() | 复制内存区域 | 1.当目标区域和源区域不存在重叠时,按照从前往后的顺序依次复制; 2.当目标区域和源区域存在重叠时,按照从后往前的顺序依次复制 |
参考资料
1.The GNU C Library (glibc),https://www.gnu.org/software/libc/
2.BYTE_COPY_FWD 源码解析,https://justinyan.me/post/1689
3.memmove vs memcpy how different? implement your own code?