2017-11-04 36 views
0

我正在學習C++。在據我所知這裏所示,該節目,str1str2店的每一個相關的字符串的第一個字符地址:爲什麼我會在一種情況下得到一個帶有字符串文字的棄用轉換警告,而不是另一種情況?

#include <iostream> 
using namespace std; 

int main() 
{ 
    char str1[]="hello"; 
    char *str2="world"; 
    cout<<str1<<endl; 
    cout<<str2<<endl; 
} 

然而,str1不給任何警告,而與str2我得到這個警告:

warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings] 
    char *str2="world"; 

這兩個聲明有什麼區別,導致在第二種情況下警告,但不是第一種?

+0

「str1和str2應存儲字符串的第一個字符的地址」。這不是真的。 'str1'存儲整個字符串本身的副本。它不存儲任何「地址」。另一方面,'str2'確實存儲地址。 – AnT

+0

HI ANT,如果副本存儲在str1中,那麼將存儲另一個「hello」副本?如果我們修改str1複製str str [0] ='H',這個改變會影響另一個副本嗎? – Bahubali

+0

最初的''hello''存儲在靜態和不可修改的內存中。當你執行'str [0] ='H''時,你修改存儲在'str1'中的副本。原稿保持不變。 – AnT

回答

3

當你寫

char str1[] = "hello"; 

你說:「請讓我的char s表示包含字符串"hello"數組,請選擇該陣列str1的尺寸爲字符串的大小對其進行初始化「。這意味着str1最終會存儲自己的字符串"hello"的唯一副本。 str1的最終類型是char[6] - 對於hello有五個,對於空終止符有一個。

當你寫

char *str2 = "world"; 

你說:「請讓我char *類型的指針指向字符串字面"world"。」字符串文字"world"的類型爲const char[6] - 它是一個由6個字符組成的數組(其中hello五個,一個用於空終止符),重要的是那些字符是const,並且無法修改。由於您使用char *指針指向該陣列,因此您將丟失const修飾符,這意味着您現在(不安全)的指針具有指向const位數據的非const指針。

的原因,事情在這裏不同的是,在第一種情況下,你所得到的字符串"hello"副本,所以實際上你的陣列是不是const是沒有問題的。在第二種情況下,您沒有獲得"hello"的副本,而是獲取指向它的指針,並且由於您正在獲得指向它的指針,因此修改它可能是一個真正的問題。

換句話說,在第一種情況下,你會得到一個由6個字符組成的誠實善良數組,其中包含hello的副本,所以如果您決定去修改這些字符,則沒有任何問題。在第二種情況下,你得到一個指向一個你不應該修改的六個字符的數組,但是你使用了一個允許你改變事物的指針。

那麼爲什麼"world"const char[6]?作爲許多系統的優化,編譯器只會將"world"的一個副本放入程序中,並且將文字"world"的所有副本指向內存中完全相同的字符串。這很好,只要你不改變那個字符串的內容。 C++語言通過說這些字符是const來強制執行此操作,所以對它們進行變異會導致未定義的行爲。在某些系統中,這種未定義的行爲會導致諸如「whoa,我的字符串文字具有錯誤值!」等情況,而在其他系統中,它可能只是段錯誤。

+0

你好,這是一個非常好的答案。我可以知道「你好」和「世界」都被視爲字符串文字嗎?或者只有「世界」被認爲是字符串文字(bcz它被分配給char *)? – Bahubali

+0

「hello」和「world」都是字符串文字。這裏的區別出現在你分配這些文字的基礎上。在第一種情況下,賦值被視爲數組初始化,所以創建了一個文字副本。第二,它是指針初始化,所以沒有複製。 – templatetypedef

0

問題是,您正試圖將字符串文字(類型爲const char *)轉換爲char *。

+0

雖然這是真的,但我不認爲它解決了OP爲什麼第一個選項不起作用的問題。 – templatetypedef

相關問題