为什么在char变量中存储255会在C中给出它的值-1?

我正在读一本C书,作者提到了一篇文章:

if ch (a char variable) is a signed type, then storing 255 in the ch variable gives it the value -1 ”。

任何人都可以详细说明吗?

假设8位char ,这实际上是实现定义的行为。 值255不能表示为带符号的8位整数。

但是,大多数实现只是存储位模式,255为0xFF 。 使用二进制补码解释,作为带符号的8位整数,即-1的位模式。 在一个更罕见的“补充”架构中,这将是负零点或陷阱表示的位模式,具有符号和幅度,它将是-127

如果两个假设中的任何一个(符号和8位char )不成立,则该值将为¹255,因为255可表示为无符号8位整数或有符号(或无符号)整数,且大于8位。

¹标准保证CHAR_BIT至少为8,可能更大。

这不是保证行为。 引用ANSI / ISO / IEC 9899:1999§6.3.1.3(在有符号和无符号整数之间进行转换)第3条:

 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised. 

我将按位/ 2的补码解释留给其他答案,但符合标准的signed char甚至不能保证太小而不能保持255; 他们可能工作得很好(给出值255.)

试试十进制。 假设我们只能有3位数。 所以我们的无符号范围是0 – 999。

让我们看看999是否真的可以表现为-1(签名):

 42 + 999 = 1041 

因为我们只能有3位数,所以我们删除最高位数(进位):

 041 = 42 - 1 

这是适用于任何数字基础的一般规则。

这就是两个补码的工作原理。 在这里阅读所有相关信息。

你在其他消息中有经典的解释。 我给你一个规则:

在大小为n的带符号类型中,MSB的存在设置为1,必须解释为-2 ^(n-1)。

对于这个具体问题,假设char的大小是8位长度(1个字节),255到二进制等于:

 1*2^(7) + 1*2^(6) + 1*2^(5) + 1*2^(4) + 1*2^(3) + 1*2^(2) + 1*2^(1) + 1*2^(0) = 255 255 equivalent to 1 1 1 1 1 1 1 1. 

对于unsigned char,你得到255,但如果你正在处理char(与signed char相同),MSB代表负数:

 -1*2^(7) + 1*2^(6) + 1*2^(5) + 1*2^(4) + 1*2^(3) + 1*2^(2) + 1*2^(1) + 1*2^(0) = -1