2016-02-24 28 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

相关问题