我是C ++的新手,正在尝试学习数组的概念。我在网上看到了这段代码。对于下面的示例代码,声明是否有任何区别:
params['song'][:filename]
as:
id
我想必须有unsigned scores[11] = {};
unsigned grade;
和int scores[11] = {};
int grade;
声明为score[11] = {};
的原因,但背后的原因是什么?
grade
答案 0 :(得分:6)
unsigned
表示variable
不会保留负值(甚至更准确 - 它不会关心标志)。很明显,scores
和grades
是无符号值(没有人得分-25
)。因此,使用unsigned
是很自然的。
但请注意:if (0 <= grade <= 100)
是多余的。 if (grade <= 100)
就足够了,因为不允许使用负值。
正如Blastfurnace评论的那样,if (0 <= grade <= 100)
是不对的。如果你想这样,你应该把它写成:
if (0 <= grade && grade <= 100)
答案 1 :(得分:4)
无符号变量
将变量声明为unsigned int
而不是int
会产生两个后果:
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个未初始化的unsigned int,其潜在值不同于0。
如果你写:
unsigned int scores[11] = {};
然后使用默认值0来初始化所有int。
请注意,如果你写:
unsigned int scores[11] = { 1, 2 };
你将第一个int初始化为1,第二个为2,其他所有为0。
您可以轻松地使用所有这些语法来进一步了解它。
<强>比较强>
关于代码:
if(0 <= grade <= 100)
如评论中所述,这并不符合您的期望。实际上,这将始终评估为true,因此在if中执行代码。这意味着如果您输入的等级为20000,则应该有一个核心转储。原因是:
0 <= grade <= 100
相当于:
(0 <= grade) <= 100
第一部分是true
(隐式转换为1)或false
(隐式转换为0)。由于两个值均低于100,因此第二个比较始终为true
。
答案 2 :(得分: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
结果,这意味着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
。< / p>
答案 3 :(得分:2)
是的确有所作为。在第一种情况下,您声明一个包含11个元素的数组,类型为&#34; unsigned int&#34;的变量。在第二种情况下,您将它们声明为整数。
当int为32位时,您可以使用以下范围中的值
-2,147,483,648至2,147,483,647 for plain int
无符号整数0到4,294,967,295
当你不需要负号时,你通常会声明一些未签名的东西,你需要无符号给出的额外范围。在您的情况下,我假设通过声明未签名的变量,开发人员不接受负分数和分数。您基本上可以统计在命令行中引入了0到10之间的等级。所以它看起来像模拟学校评分系统,因此你没有负面成绩。但阅读完代码后,这是我的意见。
看一下这篇解释unsigned是什么的帖子:
答案 4 :(得分:2)
顾名思义,有符号整数可以是负数,也可以是无符号整数。如果我们表示具有N位的整数,则对于无符号,最小值为0并且最大值为2 ^(N-1)。如果它是N比特的有符号整数,那么它可以取-2 ^(N-2)到2 ^(N-2)-1的值。这是因为我们需要1位来表示符号+/-
Ex:签名的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),但由于我们没有第四位,它只是#34;从结束时掉落&#34;我们留下了000.
同样适用于从0减去1.首先取两个补码
111 = twos_complement(001)
并将其添加到000,产生111 = -1(来自表格),这是人们可能期望的。增加011(= 3)产生100(= - 4)时会发生什么,这可能不是人们所期望的,与我们的正常预期不一致。这些溢出在定点运算中很麻烦,必须处理。
值得指出的另一件事是有符号整数可以取一个负值而不是正数,这会产生舍入的结果(例如,当使用整数表示定点数时)但是我确定这样做了更好地涵盖DSP或信号处理论坛。