不能直接用=拷贝c风格字符串指针,因为=仅复制指针地址而非内容,导致双指针共享同一内存,引发野指针、数据误改等问题;真正拷贝需逐字节复制至'\0',且目标缓冲区须≥strlen(src)+1,源/目标指针非空,末尾必须写入'\0'。

为什么不能直接用 = 拷贝 C 风格字符串指针
因为 = 只复制指针地址,不是字符串内容。两个指针指向同一块内存,修改一个会影响另一个,释放一次内存后另一指针就成野指针。
真正拷贝字符串内容,必须逐字节复制,直到遇到 '\0' 结束符。
- 目标缓冲区必须足够大(至少
strlen(src) + 1字节) - 源指针和目标指针都不能为
nullptr,否则运行时崩溃 - 别忘了在目标末尾手动写入
'\0',否则printf或strlen会越界读取
手写 my_strcpy:最简安全实现
不依赖 <cstring></cstring>,只用基础指针操作,适合教学或嵌入式环境。
char* my_strcpy(char* dest, const char* src) {
if (!dest || !src) return nullptr;
char* ret = dest;
while ((*dest++ = *src++) != '\0') ;
return ret;
}
注意:while 循环里赋值后立即判断是否为 '\0',所以 '\0' 本身也被拷贝过去。返回 dest 原始地址,方便链式调用(如 printf("%s", my_strcpy(buf, "hello"));)。
- 不要用
for (int i = 0; src[i]; i++) dest[i] = src[i];—— 多一次索引计算,且没写dest[i+1] = '\0' - 如果目标空间不足,函数不会检查,直接越界写入 —— 这是 C 风格字符串的固有风险
用 std::string 替代?什么时候该换
如果你只是想安全拷贝字符串,std::string 是更优解:自动管理内存、支持赋值、不会越界。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
但指针拷贝仍有现实场景:对接 C API(如 open()、printf())、驱动开发、裸机环境、或面试考察底层理解。
-
std::string s1 = "hello"; std::string s2 = s1;—— 深拷贝,安全简洁 - 若最终要传给 C 函数,仍需
s2.c_str()获取const char*,此时内部仍是堆上拷贝 - 频繁小字符串操作下,
std::string可能触发短字符串优化(SSO),而裸指针无此机制,性能更可预测
容易被忽略的边界:空字符串和重叠内存
上面的 my_strcpy 对空字符串(src 指向 "\0")完全正确,但对重叠内存(比如 my_strcpy(buf+1, buf))行为未定义 —— 它会把字符往前“拖”,结果错乱。
需要处理重叠时,得改用类似 memmove 的从后往前逻辑,或直接用标准库的 strcpy(它不保证重叠安全)或 memmove(保证)。
- 测试空字符串:
my_strcpy(buf, "")→buf[0]应为'\0' - 重叠场景极少出现在字符串拷贝中,但在内存块移动(如
char arr[10]内部平移)时很常见 - 生产代码中,优先用
std::copy或memmove,而不是自己实现重叠安全版本
实际写的时候,先确认是否真需要裸指针 —— 大多数现代 C++ 场景,std::string 或 std::string_view 更稳;真要用指针,务必确保目标缓冲区生命周期长于使用期,且大小已校验。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










