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 */