[英]C++ unsigned and signed conversion
我以前見過這種問題,但提供的答案並沒有讓我明白一切。 發布此問題時,通常會附上下一個示例:
#include <iostream>
int main()
{
unsigned int u = 10;
int i = -42;
std::cout << i + i << std::endl;
std::cout << i + u << std::endl;
return 0;
}
輸出:
-84
4294967264
所有按預期工作 int 轉換為無符號。 但是如果i
絕對值小於u
則似乎沒有發生這種轉換。
#include <iostream>
int main()
{
unsigned int u = 10;
int i = -3;
std::cout << i + i << std::endl;
std::cout << i + u << std::endl;
return 0;
}
輸出:
-6
7
我沒有看到任何提到它的答案,也找不到任何解釋。 盡管這似乎是合乎邏輯的事情發生,但我對此沒有任何解釋。
后:
unsigned int u = 10;
int i = -3;
i + u
的計算首先將i
轉換為unsigned int
。 對於 32 位unsigned int
,此轉換包含模 2 32 ,即 4,294,967,296。 這種包裝的結果是 -3 + 4,294,967,296 = 4,294,967,293。
轉換后,我們將添加 4,294,967,293(轉換后的i
)和 10 ( u
)。 這將是 4,294,967,303。 由於這超出了 32 位unsigned int
,因此它以 4,294,967,296 為模包裝。 其結果是 4,294,967,303 − 4,294,967,296 = 7。
因此打印“7”。
但是如果 i 的絕對值小於 u,則似乎沒有發生這種轉換。
你的假設是錯誤的:這種轉換正在發生。 “這種轉換”是指當 -3 轉換為無符號類型時,結果是 4'294'967'293。
我沒有看到任何提到它的答案,也找不到任何解釋。
無符號算術是模塊化的。 這就是模算術的工作原理。
要理解模算術,請考慮 12 小時制的工作原理。 它也是模塊化的。 您會注意到鍾面沒有任何負數:
無符號算術的工作原理正是如此。 除了在 32 位類型的情況下有 4'294'967'296 個值而不是 12 個值。
為了將不可表示的值轉換為可表示的范圍,只需添加或減去模數(時鍾情況下為 12,32 位無符號整數情況下為 4'294'967'296),直到該值處於可表示范圍內。
以下是時鍾示例的數學計算:
R ≡ 10 + (-3) (mod 12)
// -3 = 9 + (12 * -1)
R ≡ 10 + 9 (mod 12)
R ≡ 19 (mod 12)
// 19 = 7 + (12 * 1)
R ≡ 7 (mod 12)
R ≡ 10 + (-42) (mod 12)
// -42 = 6 + (12 * -4)
R ≡ 10 + 6 (mod 12)
R ≡ 16 (mod 12)
// 16 = 4 + (12 * 1)
R ≡ 4 (mod 12)
以下是您的示例的數學計算:
R ≡ 10 + (-42) (mod 4'294'967'296)
// -42 = 4'294'967'254 + (4'294'967'296 * -1)
R ≡ 10 + 4'294'967'254 (mod 4'294'967'296)
R ≡ 4'294'967'264 (mod 4'294'967'296)
R ≡ 10 + (-3) (mod 4'294'967'296)
// -3 = 4'294'967'293 + (4'294'967'296 * -1)
R ≡ 10 + 4'294'967'293 (mod 4'294'967'296)
R ≡ 4'294'967'303 (mod 4'294'967'296)
// 4'294'967'303 = 7 + (4'294'967'296 * -1)
R ≡ 7 (mod 4'294'967'296)
有兩個概念對於理解負數和無符號之間的關系非常重要。 第一個是Ones的恭維。 這是一個非常古老的標准,不再使用,但很容易理解。 負數只是每個位的非。 -1 = ~1 = 1111...1110。 補碼的問題是有兩個零 (+0/-0)。 這很快就會變得復雜。 考慮
X = 2-2 Y = -2+2 X != Y
這就是現代計算機和 C/C++ 采用二進制恭維的原因。 二元贊美下降-0(沒有這樣的事情)等等
-1 = 1111...1111 -2 = 1111...1110 so -v = ~1+1
您會看到沒有“操作”可以在有符號和無符號之間進行轉換。 在硬件中,每個都只是一個位向量。 值是有符號還是無符號,只是如何解釋位的問題。 為了證明這一點,你只需嘗試
printf("%x", -1); // print a signed value as if it was unsigned
因此,回到您的問題,任何小的 (+v) 數字都是相同的,無論是否有符號。 (signed) 1 與無符號 (1) 相同。 只有當最高位為 1 時,解釋才會改變。
順便說一句:在 C/C++ 中,“unsigned int”可以縮寫為“unsigned”,這是規則的殘余,即任何未指定的類型都被假定為 int。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.