string::c_str() 返回指向以\0结尾的const char*指针,直接映射字符串内部缓冲区,仅在原string对象有效且未修改时安全使用。
c_str() 返回一个指向以 '\0' 结尾的 const char* 的指针,内容与当前 std::string 对象一致。它不复制数据,而是直接暴露内部缓冲区(在 C++11 及以后,标准保证其内存是连续且以空字符结尾的)。
关键点:返回指针**仅在原 string 对象生命周期内、且未被修改时有效**。一旦 string 被赋值、拼接、clear() 或析构,该指针立即悬空。
下面这些写法危险:
std::string s = "hello"; char* p = const_cast(s.c_str()); // ❌ 非法转 const,且仍悬空 // ... strcpy(buf, p); // 若 s 已被修改,行为未定义
或者:
const char* global_ptr;
{
std::string tmp = "temp";
global_ptr = tmp.c_str(); // ✅ 语法通过,但 tmp 析构后 global_ptr 悬空
}
printf("%s", global_ptr); // ❌ 未定义行为const char* 接收 c_str(),不要去掉 conststrdup(s.c_str()),记得 free())或改用 std::string 本身fopen, printf, sqlite3_exec)时,只要确保 string 在 C 函数返回前不被修改,就可安全传入 c_str()
在 C++11–C++14: 在 C++11–C++14:data() 不保证结尾有 ',data() 不保证结尾有 '\0',c_str() 才是唯一带空终止符的接口。c_str() 才是唯一带空终止符的接口。
C++17 起:data() 和 c_str() 行为完全一致(都保证以 '\0' 结尾),但语义不同:c_str() 明确表示“用于 C 接口”,更清晰、更不易误用。
c_str() —— 既是习惯,也避免在旧标准编译器上出问题data() 在所有环境下都可替代 c_str(),尤其项目需兼容 C++11c_str() 仍返回合法指针,指向单个 '\0'
c_str() 本身不会“失败”,但它只截断到第一个 '\0'

std::string 是从二进制数据构造的(比如含 \x00),C 风格字符串函数会提前终止。
例如:
std::string bin = "abc\0def"; // 实际长度为 7,但 c_str() 返回的 C 字符串只有 "abc"
printf("%s\n", bin.c_str()); // 输出 abc,不是 abcdefc_str() 适合文本场景;含二进制/非空终止数据时,别用 C 字符串函数处理string.data() + string.size() 给支持长度参数的 C 函数(如 write(), send())printf("len=%zu, cstr_len=%zu\n", s.size(), strlen(s.c_str())); 快速发现隐含空字符最常被忽略的一点:c_str() 的有效性完全依赖 string 对象的生存期和不可变性——它不管理内存,也不做防御性拷贝。哪怕只是写了个日志宏里临时用了 c_str(),也要确认那个 string 在整个调用链中没被移动或销毁。