2015-04-15 92 views
1

考虑下面的程序转换无符号字符到符号的int

void main(){ 
    char t = 179; 
    printf("%d ",t); 
} 

输出为-77。 但179二进制表示是

10110011 

所以,不应该输出为-51,考虑到第1位被烧焦位。的-77 二进制表示是

11001101 

这似乎有点次序颠倒。这是怎么回事?请有人建议。

+1

http://en.wikipedia.org/wiki/Two%27s_complement – ouah

+1

为了扩展上述评论,您所期望的二进制负数编码方案称为[sign and magnitude](http:// en .wikipedia.org/wiki/Signed_number_representations#Signed_magnitude_representation),它只是使用最高有效位作为符号位。这在实践中从未被使用过。负数通常用二补数表示法来实现。 – eigenchris

+0

@eigenchris不,它不是符号大小,而是2的补码。今天很难找到1的补码或符号幅度系统。 -77和179的表示形式都是0xB3 –

回答

3

你声称-77的二进制表示是11001101,但逆转是你的。 -77的二进制表示是10110011

二进制10110011无符号是十进制的179

二进制10110011有符号是十进制的-77

您将超出范围的值179分配到signed char。理论上它可能是未定义的行为,但除了抛出一个错误之外,它将是一个非常差的编译器,它会在signed char中放置除8位值以外的任何内容。

但是当打印时,它被解释为负数,因为b7被设置。

2

看起来像char是系统上签名的类型。用于char的有效范围将是[-128,127]

通过使用

char t = 179; 

编译器使用2的179的补体(这是最有可能-77)和将该值分配给t

+0

这是未定义的行为。 –

+4

@MaximEgorushkin不是,请参阅整数转换规则。 – ouah

+0

@ouah它将一个大于CHAR_MAX的值赋给char。这是未定义的行为。 –

0

字符可以被签名或无符号:这取决于你的编译器。

如果签名,它可能是2s或1补码。

此外,它可以是大于8位时,虽然炭的sizeof被定义为1。

所以这是不可取的依赖于特定的表示。

+0

没有c14。 – ouah

+0

我们将共同发布。在下一个标准中,C++会坚持使用二进制补码:不知道C – Bathsheba

1

要积极,2的补负数您反转所有位之间转换,那么你加1

01001100(反转所有位)

01001101(加一)

也就是说77十进制

0

请注意,在许多系统上char签署。因此,当您将179(int类型)分配给char时,此值超出char范围,因此它是未指定的行为。

6.3.1.3符号和无符号的整数:

当与整数类型的值被转换为比其它_Bool另一个整数类型,如果该值可以通过新的类型来表示,它是不变的。否则,如果新类型是无符号的,则通过反复添加或减去一个无符号整数,而不是新类型中可以表示的最大值进行转换,直到该值处于新转换类型的范围内。 否则,新类型被签名并且其值不能被表示;结果是实现定义的或实现定义的信号被引发。

如果您更改类型为unsigned char您的程序将正确执行。

还要注意的是charsigned charunsigned char 3点不同的类型,不同intsigned intchar的签名是实现定义的。

+0

起初你说“它是未定义的行为”,现在你说“它是未指定的行为”,既然C具有这些措辞的特定定义。正确的说法是*结果是实现定义的或实现定义的信号被提升*。 – ouah

相关问题