首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C++ std::string 中 data()、c_str() 與內嵌空字元的正確處理

     編輯:關於C語言

string::data() 與 c_str() 的差異常導致崩潰:data() 不保證以 \0 結尾(C++11 前),c_str() 保證。實測發現行為因實作而異,唯有 c_str() 可安心配合 C API 使用。另釐清內嵌 \0 字串的正確構造方式。

核心差異

方法C++98/03C++11 起適用場景
c_str()保證以 \0 結尾保證以 \0 結尾所有需 C 風格字串的 API
data()不保證 有 \0保證以 \0 結尾(同 c_str)二進位資料、已知長度處理

舊標準下 strcpy(buf, s.data()) 極易崩潰;即便實測有 \0,亦屬未定義行為。

不可透過回傳指標修改 string 內容

data()/c_str() 回傳 const char*,僅供讀取。任何 const_cast 修改皆為未定義行為。string 內容變更(append、assign、resize 等)會使既有指標失效,必須重新取得。

包含內嵌 \0 的 string 構造

直接字面值 "abc\0def" 會在編譯期截斷,結果僅 "abc"。正確方式:

1. 建構子指定長度

string s("abc\0def", 7);  // 長度 7,含內嵌 \0
assert(s.size() == 7);
assert(s[3] == '\0');

2. append 追加指定長度

string s;
s.append("abc\0", 4);  // "abc\0"
s.append("def\0", 4);  // "abc\0def\0"

3. 配合 data() + size() 傳遞二進位資料

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;
}

最佳實務速查

  • 呼叫 C API(strcpy、printf、Win32 API) → c_str()。
  • 處理二進位 Blob、已知長度 → data() + size()。
  • 構造含 \0 字串 → 建構子 (ptr, len) 或 append(ptr, len)。
  • string 修改後 → 所有舊指標失效,重新取得。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved