【C/C++】字符串拷贝方法

以下是 C/C++ 中常见字符串拷贝方法的详细对比,涵盖安全性、性能、使用场景和现代最佳实践:


1. strcpy (C风格,不安全)

c 复制代码
char* strcpy(char* dest, const char* src);
  • 特点

    • 不检查目标缓冲区大小,可能缓冲区溢出
    • 自动添加 \0
    • 性能最高(无额外检查)。
  • 适用场景

    • 仅用于**100%确定src长度不超过dest**的情况(如硬编码短字符串)。
  • 风险示例

    c 复制代码
    char dest[5];
    strcpy(dest, "hello world"); // 崩溃!缓冲区溢出

2. strncpy (部分安全)

c 复制代码
char* strncpy(char* dest, const char* src, size_t n);
  • 特点

    • 限制最大拷贝字符数n,防止溢出。

    • 不会自动补\0 (若n <= strlen(src)),需手动处理:

      c 复制代码
      dest[n-1] = '\0'; // 手动终止
    • 性能接近strcpy

  • 适用场景

    • 固定长度缓冲区(如嵌入式系统)。
  • 示例

    c 复制代码
    char dest[10];
    strncpy(dest, "hello world", sizeof(dest));
    dest[sizeof(dest)-1] = '\0'; // 必须手动终止

3. snprintf (推荐,安全)

c 复制代码
int snprintf(char* dest, size_t size, const char* format, ...);
  • 特点

    • 完全安全:自动限制写入长度(最多size-1字符),保证\0结尾
    • 支持格式化(如拼接字符串、数字)。
    • 性能较低(需解析格式字符串)。
  • 适用场景

    • 安全拷贝或格式化字符串。
    • 现代C代码首选。
  • 示例

    c 复制代码
    char dest[10];
    snprintf(dest, sizeof(dest), "%s", "hello world"); // 自动截断并补\0

4. memcpy (二进制拷贝)

c 复制代码
void* memcpy(void* dest, const void* src, size_t n);
  • 特点

    • 直接内存拷贝,不检查\0,适合任意二进制数据。
    • 高性能(比strcpy更底层)。
    • 手动管理长度和\0
  • 适用场景

    • 已知长度的字符串或二进制数据。
    • 高性能需求(如大规模数据拷贝)。
  • 示例

    c 复制代码
    char dest[10];
    memcpy(dest, "hello", 6); // 包含\0

5. std::string (C++推荐)

cpp 复制代码
std::string dest = src;
  • 特点

    • 绝对安全:自动管理内存,无需关心缓冲区大小。
    • 支持动态扩容、拼接、查找等操作。
    • 性能略低于C风格(因堆分配)。
  • 适用场景

    • 所有C++字符串操作场景。
    • 需要高可读性和安全性的代码。
  • 示例

    cpp 复制代码
    std::string src = "hello";
    std::string dest = src; // 自动深拷贝

对比总结

方法 安全性 自动补\0 性能 适用场景
strcpy ❌ 不安全 ✅ 是 ⭐⭐⭐ 已知安全的短字符串
strncpy ⚠️ 部分安全 ❌ 需手动 ⭐⭐ 固定长度缓冲区
snprintf ✅ 安全 ✅ 是 安全拷贝或格式化字符串
memcpy ⚠️ 需手动 ❌ 需手动 ⭐⭐⭐ 已知长度的二进制数据/字符串
std::string ✅ 安全 ✅ 是 ⭐⭐ 所有C++字符串操作

最佳实践建议

  1. C++代码 :优先使用 std::string,避免手动管理内存。
  2. C代码安全拷贝 :用 snprintf(自动截断)或 strncpy + 手动补\0
  3. 高性能场景memcpy(需确保长度正确)。
  4. 绝对避免 :原生strcpy,除非能严格保证安全。

代码示例(安全拷贝)

cpp 复制代码
// C++ (推荐)
std::string src = "hello";
std::string dest = src;

// C (安全方案)
char dest[10];
snprintf(dest, sizeof(dest), "%s", "hello world"); // 自动处理

// C (高性能场景)
char dest[10];
memcpy(dest, "hello", 6); // 明确包含\0

特殊场景处理

  • Windows平台 :可用 strcpy_s(C11扩展)。
  • 动态缓冲区 :C用malloc+strcpy,C++用std::string
相关推荐
智者知已应修善业8 分钟前
【51单片机1,左边4个LED灯先闪烁2次后,右边4个LED灯再闪烁2次:2,接着所用灯一起闪烁3次,接着重复步骤1,如此循环。】2023-5-19
c++·经验分享·笔记·算法·51单片机
xiaoye-duck14 分钟前
《算法题讲解指南:优选算法-队列+宽搜》--70.N叉树的层序遍历,71.二叉树的锯齿形层序遍历,72.二叉树的最大宽度,73.在每个树行中找最大值
数据结构·c++·算法·队列
代码改善世界15 分钟前
【C++初阶】双向循环链表:List底层结构的完整实现剖析
c++·链表·list
REDcker18 分钟前
C++ 包管理工具概览
开发语言·c++
努力努力再努力wz21 分钟前
【C++高阶系列】告别内查找局限:基于磁盘 I/O 视角的 B 树深度剖析与 C++ 泛型实现!(附B树实现源码)
java·linux·开发语言·数据结构·c++·b树·算法
承渊政道22 分钟前
【优选算法】(实战攻坚BFS之FloodFill、最短路径问题、多源BFS以及解决拓扑排序)
数据结构·c++·笔记·学习·算法·leetcode·宽度优先
lcj251139 分钟前
字符函数,字符串函数,内存函数
c语言·开发语言·c++·windows
吃着火锅x唱着歌44 分钟前
深度探索C++对象模型 学习笔记 第三章 Data语意学(2)
c++·笔记·学习
Imxyk1 小时前
P9242 [蓝桥杯 2023 省 B] 接龙数列
c++·算法·图论
郝学胜-神的一滴1 小时前
二叉树后序遍历:从递归到非递归的优雅实现
数据结构·c++·程序人生·算法·