為了證明這個理論,我在代碼中做了一些實驗。這是我的代碼:
#include <stdio.h>
int main(){
unsigned int x,y,z;
if(1){
x=-5;
y=5;
z=x y;
printf("%i",z);
}
return 0;
}
但是據我所知,輸出應該是 10,但它列印的是 0,為什么會這樣?為什么我可以為 unsigned int 資料型別分配負值
uj5u.com熱心網友回復:
從 C 標準的第 6.5.16.1 節:
在簡單賦值 (=) 中,右運算元的值被轉換為賦值運算式的型別,并替換存盤在左運算元指定的物件中的值。
從第 6.3.1.3 節有符號和無符號整數:
...否則,如果新型別是無符號的,則通過在新型別中可以表示的最大值的基礎上反復加減一來轉換該值,直到該值在新型別的范圍內。
所以x=-5賦值UINT_MAX 1 - 5給x。
uj5u.com熱心網友回復:
有符號到無符號的轉換根據 C17 6.3.1.3 中的“UINT_MAX 1 的數學模數”進行:
否則,如果新型別是無符號的,則在新型別可以表示的最大值的基礎上反復加減一,直到該值在新型別的范圍內
現在碰巧的是,在 2 的補碼計算機上,這與采用有符號數的二進制表示并將其視為無符號數相同。在您的情況下-5,它表示為 binary 0xFFFFFFFB,因此無符號數最終為4294967291. 并創建一個從to4294967291 5的無符號環繞(這是明確定義的,與有符號溢位不同)。UINT_MAX = 42949672950
所以-5在轉換為無符號時不只是丟棄符號。如果這是您想要發生的,請使用abs()stdlib.h 中的函式。
uj5u.com熱心網友回復:
這是幾乎所有整數型別的一個基本特征,即它們具有可容納的已定義值范圍。但接下來的問題是,如果您嘗試設定超出該范圍的值會發生什么?對于 C 的unsigned型別,答案是它們通過模運算進行操作。
在現代機器上,typeunsigned int的范圍可能是 0 到 4294967295。顯然 -5 不適合該范圍。所以模算術說我們加或減 4294967296 的某個倍數,直到我們得到一個在范圍內的值。現在,-5 4294967296 是 4294967291,并且在范圍內,所以這就是存盤在變數中的值x。
那么x y將是 4294967296,但這也不在 0 到 4294967295 的范圍內。但是如果我們減去 4294967296,我們得到 0,這在范圍內,所以這就是我們的答案。
在此程序中,我們發現了二進制補碼演算法的作業原理。事實證明,如果我們宣告x為signedint 并將其設定為 -5,它將最終包含與 4294967291 相同的位模式。正如我們所見,4294967291 正是我們想要的位模式添加到 5 以獲得 0(即環繞后)。所以 4294967291 是用于 -5 的一個很好的內部值,因為您顯然希望 -5 5 為 0。
uj5u.com熱心網友回復:
為什么我可以為 unsigned int 資料型別分配負值?
將超出范圍的值分配給無符號型別是明確定義的。
但首先,在嘗試報告值時,代碼使用不匹配的說明符呼叫未定義行為(UB) :printf()unsigned
// printf("%i",z); // Bad
printf("%u\n",z); // Good
嘗試printf("%u %u %u %u\n", x, y, z, UINT_MAX);正確查看所有 4 個值。
x=-5;將超出范圍的值分配給unsigned. 對于無符號型別,通過添加/減去型別的最大值 1 直到在范圍內,將值轉換為范圍內的值。在這種情況下x將具有 的值UINT_MAX 1 - 5。
y=5;沒關系。
x y然后將導致無符號數學溢位。總和也以類似方式轉換為范圍內的值。
x y將具有(UINT_MAX 1 - 5) 5--> (UINT_MAX 1 - 5) 5 - (UINT_MAX 1)-->的值0。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/530483.html
標籤:C未签名签
