为什么 (int)'\xff' != 0xff 但 (int)'\x7f' == 0x7f?

Why is (int)'xff' != 0xff but (int)'x7f' == 0x7f?

本文关键字:int x7f 0x7f 为什么 xff 0xff      更新时间:2023-10-16

考虑以下代码:

typedef union
{
    int integer_;
    char mem_[4];
} MemoryView;
int main()
{
    MemoryView mv;
    mv.integer_ = (int)'xff';
    for(int i=0;i<4;i++)
        std::cout << mv.mem_[i]; // output is xffxffxffxff
    mv.integer_ = 0xff;
    for(int i=0;i<4;i++)
        std::cout << mv.mem_[i]; // output is xffx00x00x00
    // now i try with a value less than 0x80
    mv.integer_ = (int)'x7f'
    for(int i=0;i<4;i++)
        std::cout << mv.mem_[i]; // output is x7fx00x00x00

    mv.integer_ = 0x7f;
    for(int i=0;i<4;i++)
        std::cout << mv.mem_[i]; // output is x7fx00x00x00
    // now i try with 0x80
    mv.integer_ = (int)'x80'
    for(int i=0;i<4;i++)
        std::cout << mv.mem_[i]; // output is x80xffxffxff
    mv.integer_ = 0x80;
    for(int i=0;i<4;i++)
        std::cout << mv.mem_[i]; // output is x80x00x00x00
}

我用GCC4.6和MSVC2010测试了它,结果是一样的。当我尝试使用小于0x80的值时,输出是正确的,剩下的三个字节是"\xxf"。

CPU:Intel‘core 2 Duo’无尽:很少操作系统:Ubuntu 12.04LTS(64位),Windows 7(64位的)

无论类型char有符号还是无符号,都是特定于实现的


在大多数实现中(其中char中的位数为8),将0xFF的值分配给类型为char的变量可能会产生255(如果类型真的是无符号的)或-1(如果类型是真的有符号的)。

小于或等于0x7F127)的值将同时适用于无符号字符有符号字符,这解释了您获得所描述结果的原因。


#include <iostream>
#include <limits>
int
main (int argc, char *argv[])
{
  std::cerr << "unsigned char: "
            << +std::numeric_limits<unsigned char>::min ()
            << " to "
            << +std::numeric_limits<unsigned char>::max ()
            << ", 0xFF = "
            << +static_cast<unsigned char> ('xFF')
            << std::endl;
  std::cerr << "  signed char: "
            << +std::numeric_limits<signed char>::min ()
            << " to "
            << +std::numeric_limits<signed char>::max ()
            << ", 0xFF = "
            << +static_cast<signed char> ('xFF')
            << std::endl;
}

典型输出

unsigned char: 0 to 255, 0xFF = 255
  signed char: -128 to 127, 0xFF = -1

为了避免您遇到的问题,显式地将您的变量声明为有符号无符号

mv.integer_ = static_cast<unsigned char> ('xFF'); /* 255, NOT -1 */

旁注:当读取联合的一个成员时,您正在调用未定义行为,该成员不是您最后一个写信给的成员。标准没有指定在这种情况下会发生什么。当然,在大多数实现中,它将按预期工作。访问union.mem_[0]很可能会产生union.integer_的第一个字节,但这是不可保证的

'xff'的类型为char。在许多平台上,char是一个有符号积分类型,因此'xff的值是负的(-1而不是255)。当您将其转换(强制转换)为int(也有符号)时,您会得到一个具有相同负值的int。

任何严格小于0x80的东西都是正的,你会从转换中得到一个正的。

因为'xff'是一个有符号的字符(char的默认值在许多体系结构中都是有符号的,但并不总是这样)-当转换为整数时,它会进行符号扩展,使其成为32位(在本例中)int

在二进制算术中,几乎所有的负表示都使用最高位来表示"这是负的",并使用某种"逆"逻辑来表示值。最常见的是使用"二的补码",这里没有"负零"。在这种形式中,所有的1都是-1,"最负数"是一个后面跟着很多零的1,所以8位中的0x80是-128,16位中的0x8000是-32768,0x80000000是-214.7亿(以及更多的数字)。

在这种情况下,解决方案是使用static_cast<unsigned char>('xff')

基本上,存储在带符号的8位字符中的0xff-1。不带signedunsigned说明符的char是有符号的还是无符号的取决于编译器和/或平台,在这种情况下似乎是。

强制转换为int后,它将保留值-1,该值存储在一个32位带符号的int中,即0xffffffff

另一方面,存储在8位带符号字符中的0x7f127,其转换为32位int是0x0000007f