有符号和无符号数据类型有什么区别?

6
main()
{
    char i=255;
    printf("\n%x\n",i);
}

output:ffffffff

main()
{
    u_char i=255;
    printf("\n%x\n",i);
}

输出结果:ff

这里发生了什么?请用一些好的链接向我解释输出结果。我想这是非常基础的事情,但我真的很困惑...

4个回答

10
你在这里看到的问题是由两个原因造成的:
  • 255 不适合 char 范围内(请注意,char 是否等同于 signed charunsigned char 是实现定义的,但显然在您的平台上它是 signed char)。结果行为是实现定义的,但通常会回绕并变为 -1;参见 2 的补数
  • 整数提升,因为 printf() 是一个 可变参数函数。整数类型参数(如 char)自动提升为 int
所以 printf() 看到一个值为 -1int,并相应地打印其十六进制表示。
对于无符号情况,没有回绕。 printf() 看到一个值为 255int,并相应地打印其十六进制表示(省略前导零)。

请您能否再详细解释一下呢?为什么它会被提升?255在二进制中是11111111,所以2的补码应该是00000001。那么难道不应该打印0f吗? - pflz
2
@Naman:它被提升是因为这是C标准规定的。当我说“二进制补码”时,我的意思是“二进制补码算术”,而不是“该值的二进制补码”。 - Oliver Charlesworth

4

C编译器必须扩展传递给printf的值(这称为“提升”),因为printf是一种可变参数函数(它可以使用不同的参数调用)。对于类型为char的值,提升后的值为int类型。由于您的编译器的char类型似乎是有符号的,所以提升后的值被符号扩展。在二进制中:

char i = 255           // or: 11111111 in binary
int promoted_i = -1    // or: 11....11111 (usually, 32 or 64 ones)

在未签名的情况下,不会发生符号扩展:
char u = 255           // or: 11111111 in binary, same as above but with different interpretation
unsigned int pu = i    // or: 00....0011111111 (8 ones, preceded by the appropriate number of zeroes) 

0

char i = 255; 通过将一个值转换为一个它不适合的有符号类型(假设char只有8位且普通的char是有符号的,这两个都是实现特定的),调用了实现定义的行为。


0

当你将一个8位有符号变量设置为它无法容纳的值255时,在这种情况下,它似乎会将负(高端)标志设置为1,因此如果它是有符号的,则该值将为-1,但然后它被转换为整数-1,即ffffffff


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接