我在下面的代碼中想知道爲什麼i和j的結果是不同的。根據我的直覺,b還指出了值爲4的char地址。爲什麼結果i和j是不同的從char類型轉換爲int類型產生不同的結果
char c='4';
const char *b;
int i,j;
i=atoi(string(1,c).c_str());
b=string(1,c).c_str();
j=atoi(b);
cout<<i<<" "<<j<<endl;
我在下面的代碼中想知道爲什麼i和j的結果是不同的。根據我的直覺,b還指出了值爲4的char地址。爲什麼結果i和j是不同的從char類型轉換爲int類型產生不同的結果
char c='4';
const char *b;
int i,j;
i=atoi(string(1,c).c_str());
b=string(1,c).c_str();
j=atoi(b);
cout<<i<<" "<<j<<endl;
b = string(1,c).c_str();
這將創建一個臨時string
的表達後,超出範圍。問題是,只要字符串被調用並且沒有非const函數被調用,那麼由c_str()
返回的指針就是有效的。
如果您沿着這條路線行事,您需要確保當您撥打atoi
時原始string
有效。
std::string s(1,c);
b = s.c_str();
j = atoi(b);
s.clear(); // b is no longer valid now!
或者:
j = atoi(string(1,c).c_str());
在某些體系結構(os,編譯器,stl實現)中,代碼按預期產生「4 4」。試試吧here。
問題是代碼依賴於未定義的行爲,因爲它使用了一個已被銷燬的對象返回的指針。
當編寫
b = string(1,c).c_str();
要創建一個臨時對象,並要求它爲一個指向字符數組。您將此指針指定給b,然後臨時對象(擁有內存b現在指向的)被銷燬。假設庫是「理智的」,這種內存將在字符串銷燬期間被釋放。因此通過指針b訪問內存是未定義的行爲。
當然,您不應該依賴未定義的行爲,即使它在某些場合「起作用」。
b=string(1,c).c_str();
b
指向一個臨時對象,該對象在此語句後被銷燬。它實際上有未定義的行爲。
轉換字符爲int短的方法是:
int i = c- '0';
只要字符串,它被稱爲對生命_and_沒有非const函數被調用就可以了。 –
@JamesKanze謝謝,我無恥地編輯了它。 – jrok
它是否在語句'b = string(1,c).c_str()'中表示,該字符串只是一個臨時對象,因此命令'c_str'無效。 – witrus