如果我将负值分配给unsigned char,会发生什么?

时间:2016-12-22 06:19:02

标签: c c++11 unsigned

在C ++入门中它表示"如果我们为无符号类型的对象分配一个超出范围的值,则结果是值的剩余部分以目标类型可以容纳的值的数量为模。"

它给出了一个例子:

int main(){


unsigned char i = -1;
// As per the book the value of i is 255 .
}

任何人都可以向我解释一下这是如何运作的。

4 个答案:

答案 0 :(得分:5)

  

结果是值的剩余部分以目标类型可以容纳的值的数量为模

以“目标类型可以容纳的值的数量”开头。对于unsigned char,这是什么?范围从0到255(包括0和255),因此总共有256个值可以表示(或“保持”)。

通常,可以在特定无符号整数表示中表示的值的数量由2 n 给出,其中 n 是用于存储的位数那种类型。

unsigned char是一个8位类型,所以2 8 == 256,正如我们已经知道的那样。

现在,我们需要执行模数操作。在您将-1分配给unsigned char的情况下,您将拥有-1 MOD 256 == 255

通常,公式为: x MOD 2 n ,其中x是您尝试分配的值, n 是您尝试分配的类型的位宽。

更正式地说,这是在C ++ 11语言标准(第3.9.1 / 4节)中规定的。它说:

  

无符号整数,声明为无符号整数,应遵守算术模2 n 的定律,其中 n 是该特定整数大小的值表示中的位数。 *

     

* 这意味着无符号算术不会溢出,因为无法用结果无符号整数类型表示的结果是以比可以表示的最大值大1的数量为模的方式减少的。得到的无符号整数类型。

考虑模运算(以及最常见的描述)的一种更简单的方法是溢出和下溢环绕。你从-1开始,它以unsigned char(0-255)的范围下溢,因此它包围了最大可表示值(即255)。

答案 1 :(得分:2)

它在C到C ++中是等价的,但措辞不同:

  

6.3.1.3有符号和无符号整数

     

1当具有整数类型的值转换为 _Bool 以外的另一个整数类型时,如果该值可以由新类型表示,则它将保持不变。

     

2否则,如果新类型是无符号的,则通过重复地添加或减去一个可以由新类型表示的最大值来转换该值,直到该值在新类型的范围内。

     

3否则,新类型已签名且值无法在其中表示;结果是实现定义的,或者引发实现定义的信号。

答案 2 :(得分:1)

文字1的类型为int。对于这个解释,让我们假设sizeof(int) == 4最有可能。那么二进制文件中的1将如下所示:

00000000 00000000 00000000 00000001 

现在让我们应用一元减号运算符来获取-1。我们假设使用两个补码,因为它最有可能是(查找二进制补码以获得更多解释)。我们得到:

11111111 11111111 11111111 11111111

请注意,在上面的数字中,第一位是符号位。

当您尝试将此号码分配给unsigned char时,其值为sizeof(unsigned char) == 1,该值将被截断为:

11111111

现在,如果将此转换为十进制,您将获得255。这里第一位不被视为符号位,因为类型为unsigned

答案 3 :(得分:0)

用Stroustrup的话来说:

  

如果目标类型为ViewPager.addOnPageChangeListener,则结果值与源中的位数一样多(如果需要,将丢弃高位)。更确切地说,结果是与模数为2到nth的源整数一致的最小无符号整数,其中n是用于表示无符号类型的位数。

摘自C ++标准N3936:

  

对于每个标准签名整数类型,存在相应的(但不同的)无符号标准   整数类型:“ unsigned char ”,“unsigned short int”,“unsigned int”,“unsigned long int”,   和“unsigned long long int”,每个都占用相同的存储量并且具有相同的存储量   对齐要求(3.11)作为对应的有符号整数类型47;也就是说,每个有符号整数类型   与对应的无符号整数类型具有相同的对象表示。