跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

C++ string怎么转char数组 C++ strcpy与strncpy安全复制方法【转换】

c_str() 返回以\0结尾的只读C字符串指针,data()在C++17前不保证结尾有\0;二者均不可写,需显式分配内存并确保足够空间(≥长度+1)后复制,必要时手动补\0。 string.c_str() 和 string.data() 的区别与选择 直接用
string.c_str()
获取 C 风格字符串指针是最常见做法,但它返回的是
const char*
,不能用于写入;若你确实需要可修改的
char
数组(比如传给老式 C API 做输入输出),必须自己分配内存并复制内容。
string.data()
在 C++11 中也返回
const char*
(C++17 起才保证结尾有
'\0'
),所以它和
c_str()
此时行为一致,**不能替代 strcpy 目标缓冲区**。 常见错误是这样写:
std::string s = "hello"; char* buf = const_cast(s.c_str()); // 危险!底层内存不可写 strcpy(buf, "world"); // 未定义行为
要写入,必须用
new char[n+1]
或栈数组(如
char buf[256]
)显式分配空间 目标缓冲区大小必须 ≥
s.length() + 1
,否则复制会越界 复制后记得手动加
'\0'
(如果用
strncpy
且源长度 ≥ 缓冲区长度) strcpy 复制 string 到 char 数组的正确步骤
strcpy
本身不检查目标空间大小,依赖程序员确保目标足够大。从
std::string
复制时,必须先确认容量再调用:
std::string s = "test"; char buf[32]; if (s.length() < sizeof(buf)) { strcpy(buf, s.c_str()); } else { // 处理截断或报错 }
永远不要对未知长度的
string
直接调用
strcpy(buf, s.c_str())
sizeof(buf)
只对数组名有效,对指针(如
char* buf = new char[32]
)无效 若目标是堆分配内存,记得
delete[] buf
,避免泄漏 strncpy 更安全?但要注意三个陷阱
strncpy
看似安全,实则容易埋坑:它不保证目标以
'\0'
结尾,也不自动补满整个缓冲区,还可能掩盖越界问题。
std::string s = "hello world"; char buf[5]; strncpy(buf, s.c_str(), sizeof(buf)-1); buf[sizeof(buf)-1] = '\0'; // 必须手动补 '\0'
参数三(最大拷贝数)应为
sizeof(buf) - 1
,留一位给
'\0'
如果
s.length() >= sizeof(buf)
,
strncpy
不会写
'\0'
—— 必须手动补 如果
s.length() ,strncpy
会用
'\0'
填满剩余位置,浪费性能 现代 C++ 更推荐
std::copy_n
+ 手动置
'\0'
,或直接用
std::vector
更现代、更少出错的替代方案 绕过 C 风格函数,用 标准库 能避开大多数缓冲区问题: C函数速查手册(CHM版) C函数速查手册(CHM版) 下载 立即学习 “ C++免费学习笔记(深入) ”; 需要临时 C 字符串只读?直接传
s.c_str()
,无需复制 需要可修改副本且长度已知?用
std::vector v(s.begin(), s.end()); v.push_back('\0');
需要固定大小栈缓冲区?用
std::array buf{}; std::copy_n(s.begin(), std::min(s.size(), buf.size()-1), buf.begin()); buf.back() = '\0';
对接旧 API 必须传
char*
?优先封装成 RAII 类管理生命周期,而不是裸指针 +
strcpy
真正麻烦的从来不是“怎么转”,而是“谁负责释放”“是否会被改写”“下次读取前有没有被覆盖”——这些逻辑比一行
strcpy
重得多。

相关文章