贝利信息

C++ char*和string互转 C++ C风格字符串与对象转换大全【代码】

日期:2026-01-25 00:00 / 作者:穿越時空
结论:std::string转const char优先用c_str(),char转std::string需防nullptr和非空终止;非C字符串必须显式传长度构造。

直接说结论: std::stringconst char*c_str()data()char*(C 风格字符串)转 std::string 直接构造即可。但「能用」不等于「安全」,关键在生命周期和 const 正确性。

std::string → const char*:c_str() 和 data() 到底怎么选?

c_str() 返回以 \0 结尾的 C 风格字符串指针,保证兼容所有 C 函数;data() 在 C++11 中行为同 c_str(),但 C++17 起不再保证末尾有 \0(除非显式调用 c_str() 或字符串含空字符)。实际项目中,只要传给 C API(如 fopenprintfsqlite3_exec),一律用 c_str()

注意:c_str() 返回的指针仅在原 std::string 对象未被修改/析构前有效:

char* → std::string:哪些情况会出问题?

最简方式是直接构造:std::string s(p)pconst char*char*)。但隐含风险:

非空终止 char 数组 / 字节数组怎么转 string?

当你的 char 数据不是 C 字符串(例如网络包、加密结果、含

当你的 char 数据不是 C 字符串(例如网络包、加密结果、含 \0 的中间数据),绝不能用无参构造函数。必须显式传入长度:

的中间数据),绝不能用无参构造函数。必须显式传入长度:

char raw_data[] = {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x77, 0x6f, 0x72, 0x6c, 0x64}; // "Hello\0world"
std::string s(raw_data, sizeof(raw_data)); // 包含 \0 和后续字节

这样得到的 std::string 是完整 11 字节,s.length() == 11,且可安全遍历每个字节。若误用 std::string s(raw_data),则只取到第一个 \0 前的 "Hello"(5 字节)。

要不要自己写转换封装?

标准库已足够,无需封装通用转换函数。但以下场景值得加一层检查:

最易被忽略的一点:std::string 的小字符串优化(SSO)会让 c_str() 指向内部缓冲,看似“免费”,但一旦字符串变长触发堆分配,指针就变了——别对指针值做任何假设。