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

时间:2013-07-27 09:32:54

标签: c++ byte

考虑以下代码:

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 \xff\xff\xff\xff

    mv.integer_ = 0xff;
    for(int i=0;i<4;i++)
        std::cout << mv.mem_[i]; // output is \xff\x00\x00\x00

    // 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 \x7f\x00\x00\x00


    mv.integer_ = 0x7f;
    for(int i=0;i<4;i++)
        std::cout << mv.mem_[i]; // output is \x7f\x00\x00\x00

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

    mv.integer_ = 0x80;
    for(int i=0;i<4;i++)
        std::cout << mv.mem_[i]; // output is \x80\x00\x00\x00

}

我用GCC4.6和MSVC2010进行了测试,结果相同。 当我尝试使用小于0x80的值时输出是正确的但值大于0x80, 左边的三个字节是'\ xff'。

CPU:英特尔'核心2 Duo' 字节:很少 操作系统:Ubuntu 12.04LTS(64位),Windows 7(64位)

4 个答案:

答案 0 :(得分:4)

特定于实现类型char签名还是未签名


char类型的变量分配0xFF的值可能会产生255(如果类型确实未签名)或-1(如果在大多数实现中类型确实是 signed )(其中char中的位数为8)。

值小于或等于0x7F127)的值将适合 unsigned char signed char ,这解释了为什么你得到了你描述的结果。


#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

要避免您遇到的问题,请将您的变量显式声明为 signed unsigned ,在这种情况下,将您的值转换为unsigned char就足够了:

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

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

答案 1 :(得分:3)

'\xff'的类型为charchar是许多平台上的有符号整数类型,因此'\xff的值为负(-1而不是255)。当你将它转换(强制转换)为int(也是有符号的)时,你得到一个具有相同负值的int。

严格低于0x80的任何内容都是正面的,并且您会从转换中得到肯定。

答案 2 :(得分:2)

因为'\xff'是签名字符(char的默认值在许多体系结构中签名,但并非总是如此) - 当转换为整数时,它会进行符号扩展,使其成为32位(在这种情况下)int

在二进制算术中,几乎所有的负表示都使用最高位来表示“这是负的”,并使用某种“反向”逻辑来表示该值。最常见的是使用“二进制补码”,其中没有“负零”。在这种形式中,所有的都是-1,“最负数”是1后跟很多零,所以8位的0x80是-128,16位的0x8000是-32768,而0x80000000是-2147百万(以及更多数字)。

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

答案 3 :(得分:1)

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

转换为int,它保持值-1,存储在32位signed int中的值为0xffffffff

另一方面,存储在8位有符号字符中的

0x7f127,其转换为32位整数为0x0000007f