strcpy 的全称是 string copy(字符串复制),它的作用就是将一个字符串(以 \0 结尾的字符数组)从源地址完整地拷贝到目标地址。

详细解释
函数原型
你可以在 C 语言的标准头文件 <string.h> 中找到 strcpy 的声明:
char *strcpy(char *dest, const char *src);
让我们分解一下这个原型:
-
*`char strcpy
**: 函数返回一个char *` 类型的指针,也就是一个字符指针。 -
*`char dest` 第一个参数,代表 destination(目的地),它是一个指向字符数组的指针,是你想把字符串拷贝进去的地方。这个数组必须有足够大的空间来容纳源字符串,否则会导致缓冲区溢出。**
-
*`const char src
**: 第二个参数,代表 **source**(源头),它是一个指向常量字符数组的指针,是你想拷贝的字符串,使用const` 关键字表示这个函数不会修改源字符串的内容。 -
*返回值 `char
**: 函数返回的是dest` 参数,也就是目标字符串的起始地址,这样做的好处是,函数调用结束后可以方便地进行链式操作或直接使用返回的指针。
工作原理
strcpy 的工作方式非常简单和直接:
- 它从
src指向的内存地址开始,逐个字节地读取字符。 - 将读取到的字符,依次写入到
dest指向的内存地址中。 - 当它读取到
src中的 空字符\0时,它知道字符串已经结束了。 - 它会将这个
\0也拷贝到dest中,以确保目标字符串也正确地终止。 - 返回
dest的地址。
代码示例
下面是一个简单的例子,展示了如何使用 strcpy。
#include <stdio.h>
#include <string.h> // 必须包含这个头文件才能使用 strcpy
int main() {
// 1. 定义源字符串
// 字符串 "Hello" 实际上存储在字符数组中,编译器会自动在末尾添加 '\0'
char src[] = "Hello, World!";
// 2. 定义目标字符串
// 关键点:dest 数组的大小必须足够大,至少要比 src 的长度大 1,用于存放 '\0'
// "Hello, World!" 的长度是 13,加上 '\0' 14
char dest[20];
// 3. 调用 strcpy 进行拷贝
// 将 src 的内容拷贝到 dest 中
strcpy(dest, src);
// 4. 验证结果
printf("源字符串 src: %s\n", src);
printf("目标字符串 dest: %s\n", dest);
// 5. 演示返回值
char *returned_ptr = strcpy(dest, "New String");
printf("使用返回值打印: %s\n", returned_ptr); // 直接打印返回的指针指向的内容
printf("直接打印 dest: %s\n", dest); // dest 的内容已经被修改
return 0;
}
输出结果:
源字符串 src: Hello, World!
目标字符串 dest: Hello, World!
使用返回值打印: New String
直接打印 dest: New String
⚠️ 重要注意事项(非常关键!)
strcpy 虽然方便,但它也是一个非常危险的函数,因为它不进行任何边界检查,如果使用不当,会导致严重的安全漏洞。
缓冲区溢出
这是 strcpy 最大的风险,如果目标数组 dest 的大小不足以容纳源字符串 src,strcpy 会继续写入 dest 数组之外的内存区域,从而覆盖掉其他重要数据,导致程序崩溃或被黑客利用。
错误示例:
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "This is a very long string that will cause a buffer overflow!";
char dest[10]; // 目标空间太小了!
// 危险!strcpy 会将 src 的内容写入 dest,并超出 dest 的边界
strcpy(dest, src);
// 这行代码可能永远不会被执行,或者程序会直接崩溃
printf("拷贝成功: %s\n", dest);
return 0;
}
上面的代码几乎肯定会引发程序崩溃(段错误),因为它试图向只有 10 个字节大小的 dest 中写入一个超长的字符串。
如何安全地使用?
为了安全地拷贝字符串,你应该:
手动检查长度
在使用 strcpy 之前,先计算字符串长度,确保目标空间足够。
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello";
char dest[10];
// 安全的做法:先检查
if (strlen(src) < sizeof(dest)) {
strcpy(dest, src);
printf("安全拷贝: %s\n", dest);
} else {
printf("错误:源字符串太长,无法安全拷贝!\n");
}
return 0;
}
使用更安全的替代函数
现代 C 编程推荐使用更安全的函数,它们会要求你指定目标缓冲区的大小,从而避免溢出。
-
strncpy: 你可以指定最多拷贝多少个字符。// 最多拷贝 sizeof(dest) - 1 个字符,最后留一个位置给 '\0' strncpy(dest, src, sizeof(dest) - 1); // 重要:strncpy 不会自动添加 '\0',src 比 n 长,你需要手动添加 dest[sizeof(dest) - 1] = '\0';
-
snprintf(或sprintf_s): 这是目前最推荐、最安全的函数之一,它允许你指定要写入的最大字符数,并且会自动在末尾添加\0。// 最安全的方式之一 snprintf(dest, sizeof(dest), "%s", src); // 即使 src 很长,snprintf 也会保证 dest 不会溢出,并且总是以 '\0'
| 特性 | 描述 |
|---|---|
| 全称 | String Copy (字符串复制) |
| 功能 | 将 src 字符串完整拷贝到 dest 字符串中。 |
| 原型 | char *strcpy(char *dest, const char *src); |
| 返回值 | 返回 dest 的起始地址。 |
| 优点 | 简单、直接、高效。 |
| 致命缺点 | 不检查目标缓冲区大小,极易导致缓冲区溢出,是安全漏洞的主要来源。 |
| 安全建议 | 优先使用 snprintf,如果必须用 strcpy,务必确保目标空间足够大。 |
strcpy 是 C 语言中一个基础但功能强大的函数,理解它的工作原理和潜在风险对于编写安全、可靠的 C 语言程序至关重要。
