
目录
1. strdup
strdup 是 C 语言中一个常用的非标准库函数(主要出现在 POSIX 系统,如 Linux/Unix),用于动态复制字符串。其功能是分配足够的内存来复制给定的字符串,并返回指向新字符串的指针。
也就是说 strdup 复制完的数据有自己的存放地址,和原数据没有关联。
//函数原型
#include <string.h> // 头文件
char *strdup(const char *s);
strdup函数复制一个字符串,使用完后,要使用free函数释放内存,strdup函数的参数不能为NULL,一旦为NULL,就会报段错误,示例代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h> // 包含 free()
int main() {
const char *src = "Hello, strdup!";
// 复制字符串
char *copy = strdup(src);
if (copy == NULL) // 检查是否成功
{
perror("strdup failed");
return 1;
}
printf("Original: %s\n", src);
printf("Copy: %s\n", copy);
free(copy); // 必须释放内存!
return 0;
}
在使用 strdup 需要注意,其不是 C 标准库函数(C89/C99/C11/C17 均未收录),但:
- 大多数编译器(如 GCC、Clang)支持。
- Windows 下需定义 _POSIX_C_SOURCE 或使用 _strdup(需 <string.h>)。
当然如果环境不支持,你也可以自行实现:
char *my_strdup(const char *s) {
if (s == NULL) return NULL;
size_t len = strlen(s) + 1; // +1 用于结尾的 '\0'
char *copy = (char*)malloc(len);
if (copy != NULL) {
memcpy(copy, s, len); // 复制内容(包括 '\0')
}
return copy;
}
详细:
#include <stdio.h>
#include <string.h>
#include <stdlib.h> // 包含 free()
char *my_strdup(const char *s) {
if (s == NULL) return NULL;
size_t len = strlen(s) + 1; // +1 用于结尾的 '\0'
char *copy = (char*)malloc(len);
if (copy != NULL) {
memcpy(copy, s, len); // 复制内容(包括 '\0')
}
return copy;
}
int main() {
const char *src = "Hello, strdup!";
// 复制字符串
char *copy = my_strdup(src);
if (copy == NULL) // 检查是否成功
{
perror("strdup failed");
return 1;
}
printf("Original: %s\n", src);
printf("Copy: %s\n", copy);
free(copy); // 必须释放内存!
return 0;
}
2. strcpy
strcpy 是 C 语言标准库中的字符串复制函数,用于将一个字符串(包括结束符 \0)复制到另一个内存位置。与 strdup 不同,strcpy 不会自动分配内存,调用者必须确保目标缓冲区足够大。
//函数原型
#include <string.h> // 必需头文件
char *strcpy(char *dest, const char *src);
示例代码:
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, strcpy!";
char dest[20]; // 目标缓冲区必须足够大!
strcpy(dest, src); // 复制字符串
printf("Source: %s\n", src);
printf("Destination: %s\n", dest);
return 0;
}
不过在使用过程中需要注意,如果复制的字符串超过定义的内存大小,会出现缓冲区溢出的风险,例如:
char dest[5];
strcpy(dest, "This string is too long!"); // 溢出!导致未定义行为
我们可以使用 strncpy 进行限制最大复制长度:
char dest[10];
strncpy(dest, "Hello world", sizeof(dest)-1); // 限制复制长度
dest[sizeof(dest)-1] = '\0'; // 确保字符串终止
其中 strncpy 的函数原型:
#include <string.h>
char *strncpy(char *dest, const char *src, size_t n);
//dest:目标缓冲区(需预先分配内存)
//src:源字符串
//n:最大复制的字符数(包括 '\0')
示例代码:
#include <stdio.h>
#include <string.h>
int main() {
const char *src = "This is a long string that may be truncated";
char dest[20]; // 目标缓冲区较小
// 安全复制(保留空间给\0)
strncpy(dest, src, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0'; // 手动终止
printf("Source: %s\n", src);
printf("Destination: %s\n", dest); // 输出截断后的字符串
return 0;
}
3. 区别
| 特性 | strcpy | strdup |
|---|---|---|
| 内存管理 | 目标缓冲区由调用者预先分配 | 内部动态分配内存(malloc) |
| 安全性 | 高风险(不检查长度) | 需检查返回值(可能内存不足) |
| 释放内存 | 无需额外释放 | 必须显式 free() |
| 标准性 | ANSI C 标准函数 | POSIX 扩展(非 C 标准) |
| 使用场景 | 已知目标缓冲区大小 | 动态创建字符串副本 |
4. 拓展
4.1 free
free 是 C 语言中用于释放动态分配内存的核心函数。它与内存分配函数(malloc, calloc, realloc, strdup)配对使用,防止内存泄漏。
其需遵守的规则:
| 操作 | ✅ 正确做法 | ❌ 危险操作 |
|---|---|---|
| 释放次数 | 每个分配只释放一次 | 重复释放:free(p); free(p); → 崩溃 |
| 释放后访问 | 释放后立即置 NULL | free(p); printf("%s", p); → 未定义行为 |
| 内存所有权 | 谁分配谁释放 | 跨模块释放:模块A分配 → 模块B释放 → 易出错 |
| 部分释放 | 必须释放整个内存块 | 尝试释放分配块的中间位置 → 崩溃 |
| 静态内存 | 只用于堆内存 | free(&local_var) → 灾难性错误 |
举个例子:
#include <stdlib.h>
int main() {
// 1. 动态分配内存
char *buffer = malloc(100 * sizeof(char));
if (buffer == NULL) {
// 处理分配失败
return 1;
}
// 2. 使用内存...
strcpy(buffer, "Dynamic memory example");
// 3. 释放内存
free(buffer);
buffer = NULL; // 消除野指针
return 0;
}



被折叠的 条评论
为什么被折叠?



