2013-06-01 71 views
-1

我有這樣的代碼:爲什麼int指針會給我浮點數?

double x = 100.1; 
double y; 
int *p; 

p = (int *) &x; 
y = *p; 

cout << "y value is: " << y << endl; 

據我所知,這是錯的,我們得到了4個字節,而不是我們的8個字節。我也知道浮點數必須在存儲一些棘手的表示(但不知道怎麼做),但這個劇本給了我這樣的輸出:

y value is: 1.71799e+09 

據我瞭解也用浮點值。我的指針是int,我也期望int結果。爲什麼不是?我應該閱讀什麼來理解?

+1

你*得到了一個int結果。它只是使用僅適用於double的表示形式進行了格式化。因爲這是cout在傳遞double類型的變量時所做的。當然還有一個隨機值,在+/- 20億之間。 –

+1

整數約爲1717990000(由於您注意到的棘手錶示)。然後您將其轉換爲浮點並打印出來。 –

+0

GIGO。 (對於那裏的孩子來說,這是一個古老的計算術語,代表垃圾進入,垃​​圾進出) –

回答

6

我的指針是int,我也期待int結果。爲什麼不是?

因爲y是一個double,而不是一個int。現在,如果你的意思是要問爲什麼y有一個整數值,因爲它應該是一個int(必須有一個整數值)轉換成double的結果,請看下面的輸出:

std::cout << "y value is: " << std::fixed << y << '\n'; 

你應該看到的輸出是:

y value is: 1717986918.000000 

所以,y確實有一個整數值,只需用科學記數法打印出來。如果你想知道爲什麼y具有這個特定的整數值,那是因爲這是*p的值。

std::cout << "*p is: " << *p << '\n'; 

*p is: 1717986918 

如果你要看看x100.1值內存轉儲,您將看到:

66 66 66 66 66 06 59 40 

當你訪問這個作爲一個int,你66 66 66 66,其中,轉換爲十進制,是1717986918.


另一個需要注意的是,這些都不是由C++保證的。實際上,你的程序實際上並不合法,因爲當你通過指向int的指針訪問雙重x時,你違反了別名規則。您的程序可以合法並獲得相同的結果,但C++並未指定浮點值的表示,因此特定的整數值在法律上可能不同。


我應該怎麼看的懂?

這裏是與彩車的表現起着文章:http://ridiculousfish.com/blog/posts/float.html

C++沒有規定如何花車表示,但大多數C++實現使用IEEE-754,所以你也可以看一看那規範。以下是維基百科頁面的開始:https://en.wikipedia.org/wiki/IEEE_floating_point

要了解C++的別名規則,您可以找到並閱讀規範。 IIRC§3.10/ 10中涵蓋嚴格的別名。關於SO的別名還有很多問題和答案。

3

當你

y = *p; 

變量Ÿ採取INT通過p指了指,然後將其轉換爲雙精度。

假設sizeof(double)是8和sizeof(int)是4

x = 100;你把double值100 X 8個字節。然後當你做y = *p;你只能使用8個字節中的4個,作爲int的值,然後將該數字轉換爲

doubleint的二進制格式是不同的。例如。 100 as double的表示方式與100 int(更不用說尺寸差異,例如8 vs 4)相同。

See this link

4

1.71799e+09是整數1,717,99x,XXX的浮點表示。

+0

雖然這可能是事實,但它並沒有真正回答這個問題。 – Devolus

+0

@Devolus:這個問題的答案是「我也期待整數結果,爲什麼不呢?」是**,它是**。 '1.71799e + 09' **是**整數,表示爲'double'。它沒有小數部分。 – RichieHindle

+0

啊,現在我明白你的意思了。 – Devolus

4

我的指針是int,我也期待int結果。爲什麼不是?

你的指針int *,你得到一個int結果。

但是,這不是你顯示的。您正在顯示y這是一個double

1.71799e+09是你得到的int的雙重表示。

3
double x = 100.1; 
double y; 
int *p; 

p = (int *) &x;  
// Set a pointer of type integer to point at a floating point. Better C++ style 
// would be p = reinterpret_cast<int *>(&x); 
// which explains more clearly what you are doing - reinterpreting the pointer as 
// a different type. 

y = *p; 
// *p is an integer. So y is set to the value of *p, which is some crazy 
// integer value formed from the interpretation of a double as integer. 

cout << "y value is: " << y << endl; 

請參閱上面代碼中的註釋。您正在將指針指向不同類型的數據,然後想知道爲什麼變換後的二進制數字不能代表它最初表示的內容......(從技術上講,這段代碼違反了關於別名的規則 - 基本上,你爲了兩個不同的目的使用同一塊內存,編譯器在這種情況下沒有義務「做正確的事情」我懷疑它在這種特殊情況下會做什麼 - 如果你期望的是,你得到一個整數值,用一個double的四個第一個字節表示,那就是)。

如果你想y實際上包含x數量的整數表示,你想:

y = (int)x; 

有我們可以用一個指針來做到這一點的轉換沒有合理的方式。

+1

使用'reinterpret_cast'不會使代碼更加正確;它仍然是一個混淆違規,而這種特定的C風格轉換恰好是用'reinterpret_cast'來定義的。 – bames53

+0

我說它會更清楚地解釋它是對指針的重新解釋 - 我認爲它是。如果你認爲新手明白地理解(int *),那麼可以自由地這麼認爲。 –

+0

我的抱怨是,你說「正確的C++會......」,但它不是更正確。 – bames53

0

你觸發不確定behavoir當您運行下面一行:

p = (int *) &x; 

一旦觸發未定義的行爲你的問題的其餘部分對於未定義的行爲來說是毫無意義的r是沒有意義的(儘管看看你的問題的其餘部分,可能這個未定義的行爲不會影響你真正要求的東西。我不確定。)

+0

在這種情況下你可能會在評論中加入 – pinkpanther

+1

只是出於個人好奇,如何將一個int指針轉換爲一個未定義的行爲?取消引用這樣的指針可能取決於實現,但是投射?標準的哪一部分? – AlexK

相關問題