unsigned
整數有一些奇怪的屬性,你應該避免它們,除非你有一個很好的理由。獲得1額外的積極大小,或表示限制,價值可能不是負面的,是不是很好的理由。
unsigned
整數算術實現模UINT_MAX+1
。相比之下,signed
整數的操作代表了我們從學校中熟悉的自然算術。
溢出語義
unsigned
已明確定義的溢出; signed
不會:
unsigned u = UINT_MAX;
u++; // u becomes 0
int i = INT_MAX;
i++; // undefined behaviour
這有符號整數溢出測試過程中被抓,而一個無符號的溢出,會默默地做錯事的後果。因此,只有在確定要合法化溢出時才使用unsigned
。
如果你有一個約束條件,一個值可能不是負數,那麼你需要一種方法來檢測和拒絕負值; int
是完美的。一個unsigned
將接受一個負值,並默默地將其溢出爲正值。的量不大於所述數據類型的位的數目更大的unsigned
位移語義
位移總是很好的定義。 signed
的位移是不確定的,如果它會導致符號位中的1左移,或者實現定義是否會導致符號位中的1右移。因此,使用unsigned
進行某些類型的旋轉操作。
混合符號運算
內置的算術運算總是在同一類型的操作數。如果他們提供的不同類型的操作數,「通常的算術轉換」強迫他們將同種類型,有時令人驚訝的結果:
unsigned u = 42;
std::cout << (u * -1); // 4294967254
std::cout << std::boolalpha << (u >= -1); // false
有什麼區別?
減去另一個unsigned
一個unsigned
產生一個unsigned
結果,這意味着2
和1
之間的差4294967295
。
雙最大值
int
使用一個位來表示值的符號。 unsigned
將此位用作另一個數字位。所以通常,int
有31位數字,而unsigned
有32位。這個額外位通常被引用爲使用unsigned
的理由。但是,如果31位對於特定目的不夠用,則最有可能的32位也將不足,並且應該考慮64位或更多位。
函數重載
從int
到unsigned
的隱式轉換具有相同的秩從int
到double
轉換,所以下面的例子是病態形成:
void f(unsigned);
void f(double);
f(42); // error: ambiguous call to overloaded function
互操作性
許多API(包括標準庫)使用unsigned
類型,通常是出於錯誤的原因。在與這些API進行交互時,使用unsigned
以避免混合簽名操作是明智的。
附錄
所引用的片段包括表達0 <= grade <= 100
。這將首先評估0 <= grade
,總是true
,因爲grade
不能爲負數。然後它將評估true <= 100
,其總是true
,因爲true
被轉換爲整數1
,並且1 <= 100
是true
。
問問原作者的代碼。在我看來,這裏沒有理由使用'unsigned'。 – MikeMB
@MikeMB分數和分數是否爲負?如果他們不能,那麼他們應該沒有簽名。特別是,看起來成績被用作數組索引,所以它可能必須是積極的。我的建議是將未簽名,如果你現在的負值是沒有意義的 –
Off topic:'cin >> grade''cin'太愚蠢,無法正確做到這一點。輸入-1並查看「成績」結果。 – user4581301