1. 程式人生 > 其它 >C++相容C語言的遺留問題探討:char *p=“hello“;

C++相容C語言的遺留問題探討:char *p=“hello“;

技術標籤:C++語言特性

在C++中,char *p="hello"; 這種寫法是否正確呢?

我們測試下,如下所示程式碼:

	char *p1="hello";
	cout<<p1<<endl;
	cout<<(void *)p1<<endl;

編譯、執行程式碼,結果如圖:

p1輸出為hello,p1的地址為0x488001,看起來這個程式碼沒什麼問題。

警告:

雖然程式碼可以執行,但是值得注意的是,此時編譯器給出了一個警告[Warning] deprecated conversion from string constant to 'char*' [-Wwrite-strings]

這個警告的大體意思是:禁止把字串常量轉換為'char *'這種型別。

字串常量:

原來,char *p = "hello";這條語句,實際執行有兩個過程:

  • 首先,"hello"是字串常量,字串常量要放在靜態儲存區,且其內容是不能改變的。
  • 然後,再宣告字元指標p,p指向"hello"字串所處記憶體空間

我們先用例子來證明,char *p = "hello"中的"hello"是字串常量,且在靜態儲存區。

#include<iostream>
using namespace std;

int main() {
	char *p3="kk";	
	char *p1="hello";
	char *p2="hello";
	
	cout<<(void *)p3<<endl;
	cout<<(void *)p1<<endl;
	cout<<(void *)p2<<endl; 
}

輸出地址發現,p1和p2的地址是相同的,說明他們在靜態儲存區內,且只有一份字串"hello"。

而且,觀察地址發現,字串"hello"比"kk"地址大3,"kk"長度是2,其還有個字串的結束符'\0'。

所以我們可以認為如char *p="hello"中的雙引號做了3件事:

  • 申請了空間(在常量區),存放了字串
  • 在字串尾加上了'\0'
  • 返回地址給了字元指標p

總結:char *p="hello";這樣做雖然不會報錯,但是因為字串常量是存放在靜態儲存區,所以試圖對p指向的字串進行修改操作 將造成記憶體違規訪問

。所以編譯器通過警告來告訴我們最好不用這種寫法。

C++的相容

那編譯器為啥不直接讓其編譯不通過,來制止這種錯誤,而是隻警告呢?

因為C++要相容C語言,而在C語言中,這種寫法是允許的。

在C語言中並沒有字串這個型別。字串也就是字元陣列,也就是char型別的陣列。與普通陣列不同的,字串必須以'\0'作為結束符。而在C語言中,型別為T的一維陣列,其首地址等效於該型別的一維指標,即T*型。於是字串,也就是字元陣列,首地址就可以當做char *型使用了。事實上,在庫函式以及大多數使用到字串作為引數的函式中,其引數都是char *型的。

所以,C++選擇使用警告來告訴程式設計師,這種寫法是不正確的,以後再編譯是不會通過的。

const char *p

正確的寫法是什麼呢?const char *p="hello";

cosnt char *p="hello"可以避免程式設計師錯誤的對字串進行修改,所以在以後的寫法中,我們都應使用這種寫法。