C/C++ 字符串复制函数详解:strcpy, strncpy, memcpy 与 memmove
深入理解 C/C++ 字符串复制机制,掌握 strcpy、strncpy、memcpy 和 memmove 的核心差异与使用陷阱,确保内存操作的安全与高效。
C/C++ 复制函数概览
在 C/C++ 编程中,字符串和内存的复制是基础且高频的操作。这些功能主要定义在头文件 string.h 中。常用的复制函数主要有四类,它们各自适用于不同的场景:
1. char * strcpy(char* destination, const char * source);
2. char* strncpy(char* destination, const char* source, size_t num);
3. void * memcpy(void* destination, const void* source, size_t num);
4. void * memmove(void* destination, const void* source, size_t num);
函数功能与用法详解
第1步:使用 strcpy 进行简单字符串复制
目的:将源字符串完整复制到目标缓冲区。
规则:该函数从 source 指针指向的地址开始,逐个字符复制到 destination,直到遇到结束符 '\0'。复制包含结束符本身。
注意事项: strcpy 不检查 目标缓冲区的大小。如果 source 的长度大于 destination 分配的内存,会导致缓冲区溢出(Buffer Overflow),这是严重的安全漏洞。此外,源和目标内存区域不能有重叠。
第2步:使用 strncpy 控制复制长度
目的:只复制源字符串的前 n 个字符,常用于限制输入长度或填充固定大小缓冲区。
行为逻辑:
- 若
source长度小于n:复制全部字符后,继续向destination填充剩余数量的'\0',直到总数达到n。 - 若
source长度大于等于n:仅复制前n个字符,不会 自动在末尾添加'\0'。
关键陷阱: 当 source 中包含空字符('\0')时,strncpy 仍会按计数复制。例如,复制 "abc\0def" 的前 5 个字符到已初始化的缓冲区:
char des[] = "Hello,i am!";
char source[] = "abc\0def";
strncpy(des, source, 5);
执行后 des 的内容变为:`a, b, c, \0, \0, i, 空格, a, m, !`。
注意:额外的 '\0' 是填补计数不足的,它们紧跟在复制来的 'c' 后面,而不是追加在原来的字符串末尾。如果需要安全的字符串操作,建议使用 strncat 或手动确保终止符存在。
第3步:使用 memcpy 进行通用内存块复制
目的:复制任意类型的二进制数据块,而非仅限于文本字符串。
特点: memcpy 按字节数 num 严格复制,不关心内容是否为字符串,也不检查空字符('\0')。无论数据中是否包含 '\0',它都会复制指定的字节数。
限制: 源地址和目标地址的内存区域不能重叠。如果重叠,结果未定义(通常是错误的或部分丢失)。
第4步:使用 memmove 安全处理重叠内存
目的:在允许内存重叠的情况下,安全地移动数据块。
区别: memmove 的功能与 memcpy 完全相同,但它保证在源区和目标区有重叠时也能正确工作。内部实现通常会先复制到临时缓冲区,或直接根据重叠方向决定复制顺序(从前向后或从后向前)。
示例: 将字符串的一部分移动到另一部分位置:
char str[] = "This is a test!";
// 将 str+10 (即 't') 开始的 4 个字符 "test" 复制到 str+2 的位置
memmove(str + 2, str + 10, 4);
执行后,str 变为 "Thtests a test!"。可以看到,重叠区域的数据被正确地移动了。
总结与选型建议
选择正确的复制函数至关重要:
- 复制已知安全的短字符串且确定目标空间足够时,可用
strcpy,但推荐始终使用更安全的变体。 - 需要限制复制长度时,使用
strncpy,但务必记得手动为结果字符串添加'\0'(如果n小于源串长度)。 - 复制非字符串的二进制数据且无重叠风险,首选
memcpy,性能通常略优。 - 不确定是否有内存重叠风险,或数据可能来自不可信来源,使用
memmove以保安全。
以上就是 C/C++ 字符串复制函数的详细内容,更多关于 C++ 底层内存操作与安全编码的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













