代码之家  ›  专栏  ›  技术社区  ›  Community wiki

如何确定变量是有符号还是无符号?

  •  6
  • Community wiki  · 技术社区  · 2 年前

    在使用2的补码整数的C实现中,如果有符号整数为负,则最高位为 1 否则 0 .

    让我们来看看 char unsigned char ,的范围 signed char -128 127 无符号字符 0 255 ,但实际上它们的十六进制在 0x00 0xff . 我现在的问题是 烧焦 无符号字符 使用8位二进制数存储在内存中,计算机本身如何知道它是否 signed unsigned ?

    char a = 0xff; printf("%d", a); //its result is -1.
    unsigned char a = 0xff; printf("%d", a); //its result is 255.
    

    在上面的示例中 printf 了解的价值 0xff(0xff) 是签名还是未签名?这仅仅取决于 a ?

    3 回复  |  直到 2 年前
        1
  •  7
  •   Community CDub    8 年前

    例如,这里有许多相关问题 this

    你的问题不太对: signed 最高的位并不总是 1 --仅当该值为负值时。事实上 签署 unsigned “类型”是否属于完全相同的位模式,以及如何解释这些位模式 比较或提升时 由它们各自的类型定义。

    例如:

    unsigned char u = 0xFF; // decimal 255
    signed char s = 0xFF; // decimal -1
    

    您可以看到两个值是如何相同的,都设置了最高位,但它们的类型不同。

    编译器使用 type system 知道如何解释值,程序员的任务是为值分配有意义的类型。在上面的示例中,我告诉编译器 0xFF 应解释为 无符号的 值(另请参见include文件 limits.h )最大范围:

    u = 0x00; // decimal 0, CHAR_MIN
    u = 0xFF; // decimal 255, UCHAR_MAX
    

    第二个 0xFF(英尺/平方英尺) 作为一个 签署 具有最大范围的值:

    s = 0x00; // decimal 0, CHAR_MIN
    s = 0x7F; // decimal 127, SCHAR_MAX
    s = 0x80; // decimal -127, SCHAR_MIN (note how 0x7F + 1 = 0x80, decimal 127 + 1 = -127, called an overflow)
    s = 0xFF; // decimal -1
    

    对于示例中的printf %d 告诉它期望 signed int 价值根据 integer promotion rules of the C language 较小的 char 类型是符号扩展的(如果是 签署 类型)或零扩展(如果是 无符号的 类型)。以上面的示例结束:

    printf("%d", u); // passes a int 0x000000FF, decimal 128, to the function
    printf("%d", s); // passes a int 0xFFFFFFFF, decimal -1, to the function
    

    更多printf格式说明符是 here 例如 %u 在这方面你可能会感兴趣。

        2
  •  6
  •   glglgl John Dvorak    11 年前

    printf() 调用(和其他场合),整数提升规则适用。

    编译器将给定值转换为 int 这取决于字符的有符号性(编译器当然知道)。因此,根据字符的有符号性,编译器通过填充 0 位或字符的最高位。

        3
  •  3
  •   Eric Lippert    2 年前

    让我们以字符和无符号字符为例,有符号字符的范围是-128到127,无符号字符是0到255,但实际上它们的十六进制范围是0x00到0xff。

    这种说法令人困惑和误导。 0xFF 只是写255的另一种方式。你也可以说 '在十六进制中,带符号字符的范围为 -0x80 0x7F 对于带符号的字符为 0x00 0xFF(英尺/平方英尺) .'

    我现在的问题是,如果一个字符和无符号字符使用8位二进制数存储在内存中,那么计算机本身如何知道它是有符号的还是无符号的?

    电脑不知道。 通过键入单词告诉它您是想将该内存解释为有符号数字还是无符号数字 unsigned .

    在上面的示例中,printf如何知道0xff的值是有符号的还是无符号的?

    离开 printf 让我们举一个更简单的例子:

    char a = 128; 
    

    发生了什么?128大于最大可能的有符号字符(同样,假设8位字符为二进制补码)。所以价值 绕到尽可能小的值 ; 则变为-128。

    char a = 129;
    

    发生了什么?129比最大可能的带符号字符大 。所以它围绕着 第二最小可能值 , -127.

    char a = 130;
    

    这是 大于可能的最大值,因此它会绕到 第三个最小可能值 , -126.

    …跳过几个。。。

    char a = 255;
    

    这比最大的可能值大128,因此它将返回到第128个最小的可能值,即-1。

    知道了?

    好了,现在我们明白了:

    char a = 255;
    unsigned char b = 255;
    

    现在,当我们说

    int c = a;
    int d = b;
    

    ? 我们有一个带符号的整数。 a 我们已经确定已换行到-1,这在整数的范围内,因此 c 变为整数-1。 b 是无符号字符255,它在整数范围内,因此 d 成为整数 255 .

    的内存内容 b 都是不相关的。那记忆是 解释为数字 基于 类型 您分配给的 b 特别地,该位模式到整数位模式的转换完全取决于类型。