首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++字符串操作陷阱:為什麼字符指針無法修改字符串內容?

     編輯:程式設計疑難解答

現象重現

// ❌ 錯誤代碼:運行時崩潰
char* s = "12"; 
char t = s[0];
s[0] = s[1]; // Segmentation Fault / Access Violation
s[1] = t;

// ✅ 正確代碼
char s[] = "12"; // 或 char s[3] = "12";
char t = s[0];
s[0] = s[1];
s[1] = t; // 成功交換,s 變為 "21"

根本原因:內存佈局差異

寫法類型存儲區域可修改性內存圖解
char* s = "12";指向字符串字面量的指針只讀數據段 (.rodata / .text)❌ 唯讀,寫入觸發硬件異常s (棧) → "12\0" (只讀區)
char s[] = "12";字符數組棧區 (函數棧幀)✅ 可讀寫,編譯器自動複製字面量到數組s (棧) = {'1','2','\0'}

標準規定

C/C++ 標準規定:字符串字面量具有靜態存儲期限,且為不可修改。編譯器通常將其放入只讀內存頁,任何嘗試修改的行為屬於未定義行為(UB)。

正確的動態分配寫法

若必須用指針且需要修改:

// 方式 1:malloc + strcpy (C 風格)
char* s = (char*)malloc(3);
strcpy(s, "12");
// ... 修改 s ...
free(s);

// 方式 2:new + strcpy (C++ 風格)
char* s = new char[3];
strcpy(s, "12");
// ... 修改 s ...
delete[] s;

// 方式 3:std::string (現代 C++ 首選)
std::string s = "12";
std::swap(s[0], s[1]); // 安全、簡潔、自動管理內存

編譯器警示

  • GCC/Clang:`-Wwrite-strings` 會將 `char* s = "12"` 警告為「棄用轉換」,建議用 `const char*`。
  • MSVC:默認不報警,但運行時崩潰。
  • 最佳實踐:字面量賦值必加 const → `const char* s = "12";`,編譯期即可攔截修改企圖。

總結

char* s = "..." 是指向只讀區的指針,不可修改內容;char s[] = "..." 是棧上可變數組,內容可修改。現代 C++ 開發請優先使用 std::string 或 std::string_view(C++17),杜絕裸指針操作字符串,從源頭消除此類 UB。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved