strcpy or strncpy or memcpy
strcpy
头文件
#include <string.h>
函数原型
char *strcpy(char *dest, const char *src);
函数说明
strcpy() 会将参数 src 字符串拷贝至参数 dest 所指的地址。
但是如果 dest 所指向的空间不够大,可能会造成缓冲溢出(buffer Overflow)的错误情况,且复制发生在两个重叠的对象中,则这种行为未定义。
总得来说,这是个旧时代的产物,安全性得不到保障,滥用 strcpy 会在一些意想不到的地方让人掉进深坑。
返回值
返回参数 dest 的字符串起始地址。
坑点示例
#include <stdio.h>
#include <string.h>
int main()
{
char str[10];
char s[10] = "abc";
printf("s:%s\n", s); // 此时还是正常的
char *p = "abcdefghijklmnopqrstuvwxyz";
strcpy(str, p);
printf("s:%s\n", s); // 此处 s 已经被影响了
return 0;
}
输出:
s:abc
s:klmnopqrstuvwxyz
因为缓冲区溢出导致对其它变量产生了影响,这种影响是不可预测的。
strncpy
头文件
#include <string.h>
函数原型
char *strncpy(char *dest, const char *src, size_t n);
函数说明
strncpy() 会将参数 src 字符串拷贝前 n 个字符至 dest 所指的地址。
如果 src 的长度小于 n,则在 dest 后面补空字符,直到写入 n 个字符。
如果复制发生在两个重叠的对象中,则这种行为未定义。
返回值
返回参数 dest 的字符串起始地址。
memcpy
头文件
#include <string.h>
函数原型
char *memcpy(void *dest, const void *src, size_t n);
函数说明
memcpy()用来拷贝 src 所指的内存内容前 n 个字节到 dest 所指的内存地址上。与 strcpy() 不同的是,memcpy() 会完整的复制 n 个字节,不会因为遇到字符串结束 ‘\0’ 而结束 。
指针 src 和 dest 所指的内存区域不可重叠。
返回值
返回参数 dest 的字符串起始地址。
注意事项
strcpy 是依据 ‘\0’ 作为结束判断的,如果 dest 的空间不够,会引起 buffer overflow。
memcpy 用来在内存中复制数据,当数据中包含有 ‘\0’ 时,只能用 memcpy。如: “abc\0def”。
strncpy 和 memcpy 比较相似,但 strncpy 在一个终止的空字符处停止。当 n > strlen(src) 时,给 dest 后面补空字符;当 n < strlen(src) 时,dest 是没有结束符 ‘\0’ 的。
这里包含一个隐藏条件,dest 指向的内存一定会被写 n 个字符。
使用 strcpy 需要保证 dest 指向的空间要大于等于 src 指向的空间(然而在实际编程中往往忽略了这点,或者 src 并不是编写者预期的那么长)。
使用 strncpy 或 memcpy 时,dest 指向的空间要大于或等于 n。
使用 strncp 时,n 应该 >= strlen(src) + 1;这个 1 就是最后的 ‘\0’。