2014-10-20 142 views
0

我想下面的代碼片段的行爲應該是不確定的,但我只是想確保我的理解正確的事情。 比方說,我們有這樣的代碼:const char * to int cast?

#include <iostream> 

int main() 
{ 
    std::cout << "mamut" - 8 << std::endl; 
    return 0; 
} 

所以我覺得這確實是(字符*)((INT)(爲const char *) - (INT)),但在此之後的輸出是非常奇怪的,不是我期望它有任何真正的意義。所以我的問題是關於char *和int之間的轉換 - 它是未定義的,還是有一些背後的邏輯?

編輯: 我只想補充一點:

#include <iostream> 

int main() 
{ 
    const char* a = "mamut"; 
    int b = int(a); 
    std::cout << b << std::endl; 
    std::cout << &a <<std::endl; 
    // seems b!= &a 
    for(int i = 0; i<100;i++) 
    { 
     std::cout<<(const char*)((int)a - i)<<std::endl; 
    } 

    return 0; 
} 

輸出我得到足夠大的給了我一個像_Jv_RegisterClasses等 只是爲了記錄後:

std::cout << a - i << std::endl; 

產生相同的結果爲:

std::cout<<(const char*)((int)a - i)<<std::endl; 
+0

這是不確定的行爲,但不是因爲你覺得原因。 Google指針算術。 – 2014-10-20 12:31:16

+0

你似乎認爲當你減去8時'const char *'被轉換爲'int'。這個假設是錯誤的。 – user2079303 2014-10-20 12:35:24

+0

爲什麼這個假設是錯誤的?我的意思是你不能添加char *,因爲+沒有爲char * + char *定義。 – lightxbulb 2014-10-20 12:40:07

回答

5

沒有演員,你只是告訴cout你想要在字符串文字「mamut」減8字節的地址處打印字符串。你正在做指針算術。 COUT然後將打印無論發生什麼事要在該地址,或可能崩潰&燒傷,因爲訪問數組越界導致不確定的行爲。

EDIT

關於編輯由運:一個地址轉換爲int不一定導致正確數目相同的地址。地址並不一定適合在int和最重要的是,int是有符號類型,它沒有任何意義,存儲在簽訂類型的地址。

爲了保證從指針到整數轉換無損失,您需要使用uintptr_t從stdint.h。

引述C標準6.3.2.3(I相信C++是在這種情況下是相同的):

任何指針類型可以被轉換爲整數類型。除了先前指定的 ,結果是實現定義的。如果 結果不能用整數類型表示,則行爲是 未定義。結果不需要在整數類型的任何值的範圍內。

+0

問題是(int)a不給我一個地址。基本上&a!=(int)a。我的問題從一開始就是(int)a給我的。 – lightxbulb 2014-10-20 12:45:57

+0

@lightxbulb我已經在你的問題的評論中回答了。爲了完整性,我會添加評論到這個答案。 – Lundin 2014-10-20 12:47:12

+0

所以它是未定義的行爲,並做一個演員(INT)(常量字符*)實際上沒有邏輯背後呢?我的意思是演員不會產生任何合乎邏輯的結果? – lightxbulb 2014-10-20 12:50:50

1

沒有鑄造回事。 "mamut"是一個指向字符,- 8會做就可以了指針運算。你是對的,它是未定義的行爲,所以即使語義行爲是指針算術,運行時行爲也可以是字面上的任何事情。

+0

那爲什麼地址不對應我從(int)(const char *)得到的數字? – lightxbulb 2014-10-20 12:32:15

+0

我不明白你的意思。張貼更多的代碼來精確地說明你的問題。但我想強調的是,UB意味着任何事情都可能發生。這並不需要UB過去解釋。從你的代碼中移除UB,然後我們可以進一步挖掘。 – tenfour 2014-10-20 12:33:30

0

您打印字符串從「mamut」減去總8+5 = 13字符8個字節,直到空終止即地址開始