2016-02-24 80 views
3

我是C++的新手,正在嘗試學習數組的概念,我在線看到了這段代碼片段。聲明:爲什麼要聲明「score [11] = {};」和「等級」爲「無符號」而不是「int」

unsigned scores[11] = {}; 
unsigned grade; 

爲:?

int scores[11] = {}; 
int grade; 

我想一定是爲什麼score[11] = {};grade聲明爲unsigned一個原因,但它是什麼背後的原因

int main() { 
    unsigned scores[11] = {}; 
    unsigned grade; 
    while (cin >> grade) { 
     if (0 <= grade <= 100) { 
      ++scores[grade/10]; 
     } 
    } 
    for (int i = 0; i < 11; i++) { 
     cout << scores[i] << endl; 
    } 
} 
+5

問問原作者的代碼。在我看來,這裏沒有理由使用'unsigned'。 – MikeMB

+2

@MikeMB分數和分數是否爲負?如果他們不能,那麼他們應該沒有簽名。特別是,看起來成績被用作數組索引,所以它可能必須是積極的。我的建議是將未簽名,如果你現在的負值是沒有意義的 –

+1

Off topic:'cin >> grade''cin'太愚蠢,無法正確做到這一點。輸入-1並查看「成績」結果。 – user4581301

回答

4

無符號變量

變量聲明爲unsigned int代替int有2個後果:

  • 它可以」 t是負面的。它爲您提供了保證,這絕不會因此就不需要檢查並處理特殊情況編寫代碼,只有正整數工作時
  • 當你有一個有限的大小,它可以讓你大代表數字。上32位,最大unsigned int是4294967295(2^32-1),而最大的int是2147483647(2^31-1)

一個使用unsigned int的後果是,算術將在所述一組來進行unsigned int。所以9 - 10 = 4294967295而不是-1,因爲沒有負數可以在unsigned int類型上編碼。如果您將它們與負數int比較,您也會遇到問題。

More info on how negative integer are encoded.

數組初始化

對於陣列定義,如果你只寫:

unsigned int scores[11]; 

然後,你必須具有11未初始化的無符號整型可能比0

值不同

如果你這樣寫:

unsigned int scores[11] = {}; 

然後,所有INT與該是0

注意缺省值初始化,如果你寫:

unsigned int scores[11] = { 1, 2 }; 

你將有第INT初始化爲1,第二個2和所有其他爲0

您可以輕鬆地玩一點點所有這些語法來更好地瞭解它。

比較

關於代碼:

if(0 <= grade <= 100) 

如在評論中指出,這不會做你期望的。事實上,這將始終評估爲真,並因此在if中執行代碼。這意味着如果你輸入20000的等級,你應該有一個核心轉儲。其原因是這樣的:

0 <= grade <= 100 

相當於:

(0 <= grade) <= 100 

和第一部件或者是true(隱式轉換爲1)或false(隱式轉換成0)。由於兩個值都低於100,所以第二個比較始終爲true

+1

如果你想計算'score [0]'和'scores [1]'之間的差異怎麼辦? '分數[0] - 分數[1]'應該是'-1',而不是'4294967295'。 – Oktalist

+0

好點,我在答案中加入它 –

2

是的,它確實有所作爲。在第一種情況下,您將聲明一個由11個元素組成的數組,一個類型爲「unsigned int」的變量。在第二種情況下,您將它們聲明爲整數。

當int是32位的,你可以有從以下範圍內的值

2,147,483,648 2,147,483,647爲普通int

0至4,294,967,295爲unsigned int類型

你通常會定義一些未簽名的時候你不需要負數,你需要用無符號給出的額外範圍。在你的情況下,我假設通過聲明變量未簽名,開發人員不接受負分和分數。你基本上可以統計在命令行引入0到10之間的等級。所以它看起來像是模擬學校評分系統的東西,因此你沒有負面成績。但是在閱讀代碼後,這是我的看法。

看看這個帖子裏面解釋了什麼是無符號是:

what is the unsigned datatype?

6

unsignedvariable不會舉行一個負值(或者更準確的 - 它不會在意點登錄)。它似乎很明顯,scoresgrades是無符號值(沒有人得分-25)。所以,使用unsigned是很自然的。

不過需要注意的:if (0 <= grade <= 100)是多餘的。因爲沒有負值是允許的,所以if (grade <= 100)就足夠了。

由於高爐評論,if (0 <= grade <= 100)是不正確的,甚至。如果你想這樣你應該把它寫成:

if (0 <= grade && grade <= 100)

+1

你可能會提到表達式'0 <= grade <= 100'是無稽之談。 – Blastfurnace

+0

我確實做過。我錯過了什麼 ? –

+1

這個表達式幾乎可以肯定不會做OP認爲它做的事情。這不是你如何測試變量是否在兩個值之間。 – Blastfurnace

2

顧名思義,有符號整數可以是負數,無符號數不能是。如果我們用N位表示一個整數,那麼對於無符號,最小值爲0,最大值爲2 ^(N-1)。如果它是N位的有符號整數,則它可以取-2 ^(N-2)到2 ^(N-2)-1的值。這是因爲我們需要1位代表符號+/-

例如:簽訂3位整數(是有這樣的事情)

000 = 0 
001 = 1 
010 = 2 
011 = 3 
100 = -4 
101 = -3 
110 = -2 
111 = -1 

但是,對於無符號只是代表值[ 0,7]。示例中最重要的位(MSB)表示負值。也就是說,MSB設置的所有值都是負值。因此,它的絕對值顯然有點損失。

它也表現得像人們所期望的那樣。如果你增加-1(111),我們得到(1 000),但由於我們沒有第四位,它只是「落底」,我們留下了000.

同樣適用於從0先取補

111 = twos_complement(001) 

,並把它添加到000這將產生111 = -1(從表中),而這正是人們所預料的。當你增加011(= 3)產生100(= - 4)時,會發生什麼可能不是我們所期望的,並且與我們的正常期望不符。這些溢出對定點算術來說是麻煩的,必須處理。

另一件值得指出的事情是,帶符號的整數可以帶一個負值,而不是正值,這會導致舍入的結果(例如使用整數表示固定點數),但肯定會更好地覆蓋DSP或信號處理論壇。

3

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結果,這意味着21之間的差4294967295

雙最大值

int使用一個位來表示值的符號。 unsigned將此位用作另一個數字位。所以通常,int有31位數字,而unsigned有32位。這個額外位通常被引用爲使用unsigned的理由。但是,如果31位對於特定目的不夠用,則最有可能的32位也將不足,並且應該考慮64位或更多位。

函數重載

intunsigned的隱式轉換具有相同的秩從intdouble轉換,所以下面的例子是病態形成:

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 <= 100true

相關問題