strcpy(String Copy):专门用于复制以\0(空字符) 结尾的字符串,它会复制源字符串的所有字符,直到遇到\0为止,并在目标空间的末尾自动添加\0。memcpy(Memory Copy):通用的内存块复制函数,它按字节复制指定大小的内存内容,是什么(可以是字符串、整数、结构体等),也不关心\0。
strcpy (String Copy)
strcpy 是字符串操作的基石之一。

(图片来源网络,侵删)
函数原型
#include <string.h> char *strcpy(char *dest, const char *src);
功能
将源字符串 src(Source)的内容复制到目标字符串 dest(Destination)中,直到遇到源字符串的结束符 \0,并在 dest 的末尾也添加一个 \0。
参数
dest: 目标字符数组(字符串)的指针,必须有足够的空间来容纳源字符串,包括结尾的\0。src: 源字符数组(字符串)的指针,通常是一个字符串字面量或另一个字符数组。
返回值
返回指向目标字符串 dest 的指针。
优点与缺点
- 优点:专门为字符串设计,使用简单直观。
- 致命缺点:不安全。
strcpy不会检查目标缓冲区dest的大小。src字符串的长度超过了dest的大小,就会发生缓冲区溢出,这可能导致程序崩溃、数据损坏,甚至被黑客利用进行恶意攻击。
代码示例
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, World!";
// 必须确保 dest 的大小足够容纳 src 的内容 + '\0'
// "Hello, World!" 有 13 个字符,加上 '\0' 共 14 个
char dest[14];
strcpy(dest, src);
printf("源字符串: %s\n", src);
printf("目标字符串: %s\n", dest);
return 0;
}
安全替代方案:strncpy
为了解决 strcpy 的不安全问题,C 标准库提供了 strncpy。
char *strncpy(char *dest, const char *src, size_t n);
strncpy 会从 src 复制最多 n 个字符到 dest。

(图片来源网络,侵删)
src的长度小于n,dest的剩余部分会用\0填充。src的长度大于或等于n,dest不会自动添加\0,这可能导致dest不是合法的字符串,使用strncpy时需要手动确保dest以\0
memcpy (Memory Copy)
memcpy 是更底层、更通用的内存操作函数。
函数原型
#include <string.h> void *memcpy(void *dest, const void *src, size_t n);
功能
从源内存地址 src 处开始,复制 n 个字节的数据到目标内存地址 dest 处,它是一个纯粹的内存拷贝,对数据类型一无所知。
参数
dest: 目标内存块的指针。src: 源内存块的指针。n: 要复制的字节数。这个参数是必须的,也是memcpy安全的关键。
返回值
返回指向目标内存块 dest 的指针。
优点与缺点
- 优点:
- 高效:现代编译器对
memcpy有高度优化。 - 安全:因为需要指定要复制的字节数,只要
n不超过dest的大小,就不会发生缓冲区溢出。 - 通用:可以复制任何类型的数据,而不仅仅是字符串。
- 高效:现代编译器对
- 缺点:对于字符串,使用起来比
strcpy稍显繁琐,需要手动计算长度或确定要复制的字节数。
代码示例
示例 1:复制字符串

(图片来源网络,侵删)
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, Memory!";
char dest[20];
// sizeof(src) 会计算字符串长度 + 1 (给 '\0' 的空间)
memcpy(dest, src, sizeof(src));
printf("源字符串: %s\n", src);
printf("目标字符串: %s\n", dest);
return 0;
}
示例 2:复制整数数组
strcpy 无法完成这个任务,但 memcpy 可以。
#include <stdio.h>
#include <string.h>
int main() {
int src_arr[] = {10, 20, 30, 40, 50};
int dest_arr[5];
// sizeof(src_arr) 得到整个数组占用的字节数
memcpy(dest_arr, src_arr, sizeof(src_arr));
printf("源数组: ");
for (int i = 0; i < 5; i++) {
printf("%d ", src_arr[i]);
}
printf("\n");
printf("目标数组: ");
for (int i = 0; i < 5; i++) {
printf("%d ", dest_arr[i]);
}
printf("\n");
return 0;
}
strcpy vs memcpy 对比总结
| 特性 | strcpy |
memcpy |
|---|---|---|
| 全称 | String Copy (字符串拷贝) | Memory Copy (内存拷贝) |
| 目的 | 专门用于复制 C 风格字符串 | 通用的内存块拷贝 |
| 复制单位 | 字符 (直到遇到 \0) |
字节 |
| 结束条件 | 遇到源字符串的 \0 |
复制了指定的 n 个字节 |
| 安全性 | 不安全,易发生缓冲区溢出 | 相对安全,只要 n 不越界 |
| 参数 | dest, src (两个指针) |
dest, src, n (两个指针 + 一个大小) |
| 数据类型 | 只能处理 char 数组 |
可以处理任何数据类型 (int, float, struct 等) |
| 性能 | 可能比 memcpy 稍慢 (需要检查 \0) |
通常非常快,编译器优化得好 |
| 使用场景 | 确定源和目标都是字符串,且对性能要求不高,或者代码可读性优先时 | 处理非字符串数据、处理固定大小的数据块、追求高性能和安全性时 |
安全性警告与最佳实践
在现代 C/C++ 编程中,直接使用 strcpy 是强烈不推荐的,即使是 memcpy,也需要程序员自己确保 n 的正确性。
更安全的现代替代方案:
-
对于 C++ (推荐
std::string和std::vector)- 字符串:使用
std::string,它会自动管理内存,从根本上杜绝了缓冲区溢出的风险。#include <string> std::string src = "Hello, C++"; std::string dest = src; // 安全、简单
- 字符串:使用
-
对于 C (使用安全函数)
- 字符串:使用
strncpy,并记得手动添加\0,或者更安全的snprintf。char dest[10]; snprintf(dest, sizeof(dest), "%s", src); // 更安全,会自动截断
- 内存块:使用
memcpy,但要确保n正确,或者使用 C11 标准引入的memcpy_s(在支持的环境下)。// memcpy_s 是 C11 的安全版本,在 Windows (MSVC) 上支持较好 // errno_t memcpy_s(void *dest, rsize_t dest_size, const void *src, rsize_t n);
- 字符串:使用
strcpy:一个历史悠久但危险的函数,在新的代码中应尽量避免使用。memcpy:一个强大、高效且相对安全的通用内存拷贝函数,当你需要复制一块固定大小的内存时,它是首选。- 核心思想:
strcpy是“按逻辑拷贝”(遇到\0停止),而memcpy是“按字节拷贝”(拷贝你指定的字节数),理解这个区别是掌握它们的关键。
