为什么 (int)'\xff' != 0xff 但 (int)'\x7f' == 0x7f?
Why is (int)'xff' != 0xff but (int)'x7f' == 0x7f?
考虑以下代码:
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
(如果类型是真的有符号的)。
小于或等于0x7F
(127
)的值将同时适用于无符号字符和有符号字符,这解释了您获得所描述结果的原因。
#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
。不带signed
或unsigned
说明符的char
是有符号的还是无符号的取决于编译器和/或平台,在这种情况下似乎是。
强制转换为int后,它将保留值-1,该值存储在一个32位带符号的int中,即0xffffffff
。
另一方面,存储在8位带符号字符中的0x7f
是127
,其转换为32位int是0x0000007f
。
- 为什么在全局范围内使用"extern int a"似乎不行?
- int(c) 和 c-'0' 之间的区别。C++
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 为什么野牛仍在使用"int yylex(void)",却找不到"int yylex(YYS
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 是否可以从int转换为enum类类型
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 'short int'持有的值溢出,但"自动"不会溢出?
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 调用'begin(int [n])'没有匹配函数
- 没有显式声明的int[]中的foreach
- 在c++中访问int到类对象的映射时出错
- 为什么我无法更改"set<set>"循环中的值<int>
- 长 长 int 不要 长 int 好
- C++程序在循环后给出奇怪的int值
- 如何计算数据类型的范围,例如int
- 如果"new int"返回"int*",那么为什么"new int[n]"不返回"int**"?
- 为什么 (int)'\xff' != 0xff 但 (int)'\x7f' == 0x7f?