string::data() 與 c_str() 的差異常導致崩潰:data() 不保證以 \0 結尾(C++11 前),c_str() 保證。實測發現行為因實作而異,唯有 c_str() 可安心配合 C API 使用。另釐清內嵌 \0 字串的正確構造方式。
| 方法 | C++98/03 | C++11 起 | 適用場景 |
|---|---|---|---|
c_str() | 保證以 \0 結尾 | 保證以 \0 結尾 | 所有需 C 風格字串的 API |
data() | 不保證 有 \0 | 保證以 \0 結尾(同 c_str) | 二進位資料、已知長度處理 |
舊標準下 strcpy(buf, s.data()) 極易崩潰;即便實測有 \0,亦屬未定義行為。
data()/c_str() 回傳 const char*,僅供讀取。任何 const_cast 修改皆為未定義行為。string 內容變更(append、assign、resize 等)會使既有指標失效,必須重新取得。
直接字面值 "abc\0def" 會在編譯期截斷,結果僅 "abc"。正確方式:
string s("abc\0def", 7); // 長度 7,含內嵌 \0
assert(s.size() == 7);
assert(s[3] == '\0');
string s;
s.append("abc\0", 4); // "abc\0"
s.append("def\0", 4); // "abc\0def\0"
void send(const char* p, size_t len); // 接收端知長度 send(s.data(), s.size()); // 正確,不依賴 \0
#include#include #include using namespace std; int main() { string s1 = "98765432109876543210A"; char buf[256]; // c_str() 安全 strcpy(buf, s1.c_str()); cout << "c_str copy ok\n"; // data() 風險(C++11 前) // strcpy(buf, s1.data()); // 危險! // 內嵌 \0 測試 string s2("123\0abc", 7); cout << "size=" << s2.size() << " len=" << strlen(s2.c_str()) << "\n"; // 輸出: size=7 len=3 (strlen 遇 \0 停止) return 0; }
strcpy、printf、Win32 API) → c_str()。data() + size()。(ptr, len) 或 append(ptr, len)。