我来自this question,在那里我想将2个整数写入一个字节,这些字节的位置介于0-16(每个4位)之间。
现在,如果我关闭文件,并运行另一个读取....
的程序for (int i = 0; i < 2; ++i)
{
char byteToRead;
file.seekg(i, std::ios::beg);
file.read(&byteToRead, sizeof(char));
bool correct = file.bad();
unsigned int num1 = (byteToRead >> 4);
unsigned int num2 = (byteToRead & 0x0F);
}
问题是,有时候这有效,但有时候我的第一个数字是负数,第二个数字总是10或9,而且肯定不是我写的数字! / p>
所以在这里,例如,前两个数字有效,但下一个数字不起作用。例如,上面读取的输出将是:
At byte 0, num1 = 5 and num2 = 6
At byte 1, num1 = 4294967289 and num2 = 12
在字节1处,num1应为9.看起来12写得很好但是9&lt;&lt; 4不工作。我端的byteToWrite是byteToWrite -100 'œ''
我检查了this question我认为有类似的问题,但我觉得我的结尾就在这里。
答案 0 :(得分:1)
右移运算符保留最左位的值。如果移位前最左边的位为0,则移位后仍为0;如果是1,那么在班次后它仍然是1。这样可以保留价值的标志。
在你的情况下,你将9(0b1001)和12(0b1100)组合在一起,所以你写0b10011100(0x9C)。第7位是1.
当byteToRead右移时,得到0b11111001(0xF9),但它被隐式转换为int。从char到int的转换也保留了值的符号,因此它产生0xFFFFFFF9。然后隐式int被隐式转换为unsigned int。所以num1包含0xFFFFFFF9,即4294967289。
有两种解决方案:
答案 1 :(得分:1)
问题源于byteToRead >> 4
。在C中,任何算术运算都至少以int
精度执行。所以首先发生的是byteToRead
被提升为int。
这些促销活动是保值的。您的系统已经签名为char
,即范围-128
到127
。您的char最初可能是-112
(位模式10010000
),然后在升级到int后,它保留其值-112
(位模式11111...1110010000
)。
负值的右移是实现定义的,但常见的实现是进行算术移位&#34;,即执行除以2;因此,您最终会得到byteToRead >> 4
为-7
的结果(位模式11111....111001
)。
将-7
转换为unsigned int
会导致UINT_MAX - 6
,即4295967289,因为无符号算术被定义为包围mod UINT_MAX+1
。
要解决此问题,您需要在执行算术之前转换为unsigned。您可以将byteToRead
投射(或别名)到unsigned char
,例如:
unsigned char byteToRead;
file.read( (char *)&byteToRead, 1 );