为什么无符号整数1比字符y-1小1?

8
main() {
    unsigned x = 1;
    char y = -1;

    if (x > y)
        printf("x>y");
    else
        printf("x<=y");
}

我本以为会出现 x>y 的情况, 但是我不得不将 unsigned int 改为 signed int 才能得到预期的结果。


char y=-1; 应该会抛出错误,我认为应该改为 char y='-1'。 - Devjosh
@Devjosh,你错了。‘-1’不是一个有效的字符。 - taskinoor
2
@Devjosh 不,实际上我正在将值(而不是ASCII)放入有符号字符数据类型中(-128到127)。 - Furqan
好的,谢谢@taskinoor和Lekensteyn,我明白了 :) - Devjosh
@Lekensteyn:字符常量具有整数类型,而具有多个字符的字符常量的值是实现定义的。(ISO C99 §6.4.4.4 ¶10) - ninjalj
显示剩余4条评论
2个回答

15

如果char等同于signed char

  • char被提升为int(整数提升,ISO C99 §6.3.1.1 ¶2)
  • 由于intunsigned int的等级相同,因此将int转换为unsigned int(算术转换,ISO C99 §6.3.1.8)

如果char等同于unsigned char

  • char可以被提升为intunsigned int之一:
    • 如果int可以表示所有的unsigned char值(通常是因为sizeof(int) > sizeof(char)),则将char转换为int
    • 否则(通常是因为sizeof(char)==sizeof(int)),将char转换为unsigned
  • 现在我们有一个操作数是intunsigned int,另一个是unsigned int。 将第一个操作数转换为unsigned int

整数提升: 如果int可以容纳原始类型的所有值,则将较低等级类型的表达式转换为int,否则转换为unsigned int

算术转换: 尝试转换为更大的类型。 当有符号和无符号之间冲突时,如果较大(包括两种类型具有相同等级的情况)的类型是无符号的,则选择无符号类型。 否则,在它能表示两种类型的所有值的情况下只选择有符号类型。

转换为整数类型(ISO C99 §6.3.1.3):

将超出范围的值转换为无符号整数类型时,使用环绕方式(模运算)实现。

将超出范围的值转换为有符号整数类型是由实现定义的,并且可能会引发一个信号(如SIGFPE)。


由于缺乏睡眠而导致的精神失常。 - ninjalj
2
+1 详细和正确的答案。(因为当被接受的答案是错误的时候,我几乎总是会+1个像样的正确答案。) - R.. GitHub STOP HELPING ICE

3

在单个操作中使用有符号和无符号时,C语言的自动类型转换会将有符号类型提升为无符号类型。如果将 -1 的位模式视为无符号数,则它是一个非常非常大的值。因此,x > y 是错误的。


1
@taskinoor:无论-1的位模式被视为无符号数,重要的是当它被转换为无符号类型时的值。 - CB Bailey
@Charles Bailey,那就是我想说的。也许我的语言表达不够好。 - taskinoor
3
当你谈论-1的位模式时,我觉得你在暗示从char隐式提升为unsigned取决于实现中char的底层表示(例如二进制补码),这是不正确的。 - CB Bailey
1
-1的位模式是无关紧要的。转换为无符号数是一种算术操作,而不是位模式重新解释。 - R.. GitHub STOP HELPING ICE

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