C++ 为什么是(int)和#x27\xff';!=0xff但是(int)和#x27\x7f';==0x7f?

C++ 为什么是(int)和#x27\xff';!=0xff但是(int)和#x27\x7f';==0x7f?,c++,byte,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

考虑以下代码:

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

}
typedef联合
{
整型整数;
char mem_u4];
}记忆视图;
int main()
{
MemoryView mv;
mv.integer_=(int)'\xff';

对于(int i=0;i基本上,存储在有符号8位字符中的
0xff
-1
。没有
signed
unsigned
说明符的
char
是有符号的还是无符号的取决于编译器和/或平台,在这种情况下,它似乎是有符号的

转换为int时,它保留值-1,该值存储在32位有符号int中,即
0xffffff


0x7f
另一方面,存储在8位有符号字符中的是
127
,转换为32位整数的是
0x0000007f
,基本上,存储在有符号8位字符中的
0xff
-1
。无
signed
unsigned
说明符是有符号的还是无符号的取决于它在编译器和/或平台上,在本例中似乎是

转换为int时,它保留值-1,该值存储在32位有符号int中,即
0xffffff


另一方面,存储在8位有符号字符中的
0x7f
127
,转换为32位整数的是
0x0000007f
'\xff'
的类型是
char
char
在许多平台上是有符号整数类型,因此
'\xff
的值是负数(
-1
而不是
255
)。当您将其转换(强制转换)为
int
(也有符号)时,将得到一个具有相同负值的int


任何严格小于
0x80
的值都将是正数,您将从转换中得到正数。

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


任何严格小于
0x80
的值都将为正,并且您将从转换中获得正值。

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

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


在这种情况下,一个解决方案是使用
static\u cast('\xff')

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

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

在这种情况下,解决方案是使用
static\u cast('\xff')

类型
char
是有符号还是无符号取决于具体的实现


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

小于或等于
0x7F
127
)的值将同时包含在无符号字符和有符号字符中,这解释了获得所描述结果的原因



为了避免出现显式声明变量为有符号或无符号的问题,在这种情况下,将值转换为
无符号字符
就足够了:

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

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

类型
char
是有符号的还是无符号的取决于具体的实现


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

小于或等于
0x7F
127
)的值将同时包含在无符号字符和有符号字符中,这解释了获得所描述结果的原因



为了避免出现显式声明变量为有符号或无符号的问题,在这种情况下,将值转换为
无符号字符
就足够了:

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

旁注: 您正在调用未定义的行为
mv.integer_ = static_cast<unsigned char> ('\xFF'); /* 255, NOT -1 */