C语言菜鸟入门·浅析strdup和strcpy的区别

目录

1.  strdup

2.  strcpy

3.  区别


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.  区别

特性strcpystrdup
内存管理目标缓冲区由调用者预先分配内部动态分配内存(malloc
安全性高风险(不检查长度)需检查返回值(可能内存不足)
释放内存无需额外释放必须显式 free()
标准性ANSI C 标准函数POSIX 扩展(非 C 标准)
使用场景已知目标缓冲区大小动态创建字符串副本

4.  拓展

4.1  free

        free 是 C 语言中用于释放动态分配内存的核心函数。它与内存分配函数(malloc, calloc, realloc, strdup)配对使用,防止内存泄漏。

        其需遵守的规则:

操作✅ 正确做法❌ 危险操作
释放次数每个分配只释放一次重复释放:free(p); free(p); → 崩溃
释放后访问释放后立即置 NULLfree(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;
}

C语言_时光の尘的博客-优快云博客

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时光の尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值