char *Sp = "Example One"; char Sa[] = "Two"; cout << Sp << &Sa[0]; // 輸出字符串內容,而非地址
為什麼 cout 輸出的是字符串而不是地址?
"Example One" 存放在**只讀數據段**(.rodata),編譯器分配匿名字符數組,以 \0 結尾。const char*,C++ 允許隱式轉 char* 但已棄用)。Sp 指向這塊只讀內存,**修改行為未定義**。Sa[]Sa 是數組標識符,大多數語境下退化為 char*(首元素地址)。&Sa[0] 顯式取首元素地址,類型 char*。cout 的重載決議operator<<(ostream&, const char*) 被定義為**輸出以指針為起始的 C 字符串**(直到 \0)。cout << Sp、cout << &Sa[0] 觸發此重載,**打印字符串內容**。cout << (void*)Sp 或 cout << (const void*)Sp。| 特性 | char *p = "lit" | char a[] = "lit" | std::string s = "lit" |
|---|---|---|---|
| 存儲區域 | 只讀數據段 (.rodata) | 棧 (局部) / 數據段 (全局/靜態) | 堆 (動態分配) |
| 可修改性 | **不可修改** (UB) | 可修改 | 可修改 |
| 大小 | 指針大小 (4/8) | 字符串長度+1 (含\0) | 動態 (含容量) |
sizeof | 指針大小 | 數組總字節數 | 對象大小 (非字符串長度) |
| 賦值/拷貝 | 淺拷貝 (只複製指針) | 不可整體賦值 (需 strcpy) | 深拷貝 (複製內容) |
| 生命週期 | 程序全程 | 作用域結束銷毀 | RAII 自動管理 |
const char* 或 string_view (C++17)。std::string。(void*) 強轉**,避免誤觸發字符串重載。