C++ 无符号整型-移位和oring创建负值

C++ 无符号整型-移位和oring创建负值,c++,c,bit-manipulation,bit-shift,C++,C,Bit Manipulation,Bit Shift,我正在读取wav文件的标题,并在从文件中读取原始字节时使用uBytesPerSecond=0x00000000 此->uBytesPerSecond uBytesPerSecond |=数据[0x1E]//0x02->uBytesPerSecond=0x00000002 此->uBytesPerSecond uBytesPerSecond |=数据[0x1D]//0xb1->uBytesPerSecond=0xffffffb1!!! 此->uBytesPerSecond uBytesPerSec

我正在读取
wav
文件的标题,并在从文件中读取原始字节时使用
uBytesPerSecond=0x00000000
此->uBytesPerSecond uBytesPerSecond |=数据[0x1E]//0x02->uBytesPerSecond=0x00000002
此->uBytesPerSecond uBytesPerSecond |=数据[0x1D]//0xb1->uBytesPerSecond=0xffffffb1!!!
此->uBytesPerSecond uBytesPerSecond |=数据[0x1C]//0x10->uBytesPerSecond=0xffffb110
这种情况下的预期输出是
uBytesPerSecond=0x00002b110
。请告诉我这里发生了什么,我如何解决这个问题


我使用的是
MSVC2012
和Windows 8,这是一个
VC++-控制台
-应用程序。

问题是,对于您的平台,
char
是一种签名类型。因此,对于or操作,包含的值将被符号扩展到32位,为
数据[0x1D]
提供
0xffffb1

要解决这个问题,只需将
数据的类型更改为
无符号字符*


编辑:如注释中所述,该问题的另一个解决方案是使用
0xFF
显式屏蔽操作数:
this->uBytesPerSecond |=data[0x1F]&0xFF
等等。

问题是对于您的平台
char
是有符号类型。因此,对于or操作,包含的值将被符号扩展到32位,为
数据[0x1D]
提供
0xffffb1

要解决这个问题,只需将
数据的类型更改为
无符号字符*


编辑:如注释中所述,该问题的另一个解决方案是使用
0xFF
显式屏蔽操作数:
this->uBytesPerSecond |=data[0x1F]&0xFF
等等。

为什么不使用并集,而不使用按位或和移位?差不多

union ByteWord
{
    unsigned int word;
    char bytes[sizeof(unsigned int)];
}
那你就做吧

ByteWord data;
myStream.read(data.bytes, sizeof(unsigned int));
this->uBytesPerSecond = myStream.word;

如果需要字节交换,请使用
ntohl(myStream.word)

为什么不使用并集而不是按位或和移位?差不多

union ByteWord
{
    unsigned int word;
    char bytes[sizeof(unsigned int)];
}
那你就做吧

ByteWord data;
myStream.read(data.bytes, sizeof(unsigned int));
this->uBytesPerSecond = myStream.word;


如果需要字节交换,请使用
ntohl(myStream.word)

如果不包含
数据
,很难说出哪里出了问题。请查看每行上的注释
/
好,现在我明白了。谢谢。如果不包含
数据
,很难说出哪里出了问题。请查看每行上的注释
/
好,现在我明白了。谢谢。好的,这听起来不错,但有两件事:我看到了一些关于掩蔽的东西,比如
&0xFF
,这有帮助吗?其次,
fstream::read
,因为它需要
char*
作为缓冲区。@bash.d:是的,使用
数据[…]和0xFF进行掩蔽也可以(只要
char
是8bit,这对于当今的普通平台来说是一种安全的选择。关于
fstream::read
:那么,您可以
重新解释从
char*
unsigned char*
(或者相反)但是,使用显式掩蔽可能是更干净的解决方案,因为重新解释投射总是有点不确定(虽然这应该没问题,因为标准对严格的别名有明确的Axception,当涉及到
char*
时,我会试一试,谢谢!编辑->这帮我做到了,谢谢!小心屏蔽。如果你用0xFF屏蔽一个char,它可能仍然是符号扩展的,因为此时表达式仍然是一个char。它将是最好执行
static_cast()
@OliverD:考虑到
0xFF
的类型是
int
,它将对扩展
数据[…]进行签名
在掩码操作之前,只是为了使用and去掉符号扩展。好吧,这听起来不错,但有两件事:我看到了一些关于掩码的东西,比如
&0xFF
,这有帮助吗?其次,对于
fstream::read
,它需要
字符*
作为缓冲区。@bash.d:是的,使用
数据[…]进行掩码&0xFF
也可以使用(只要
char
是8位,这是当今常见平台的安全选择。关于
fstream::read
:您可以
重新解释
char*
unsigned char*
(或者相反)但是,使用显式掩蔽可能是更干净的解决方案,因为重新解释投射总是有点不确定(虽然这应该没问题,因为标准对严格的别名有明确的Axception,当涉及到
char*
时,我会试一试,谢谢!编辑->这帮我做到了,谢谢!小心屏蔽。如果你用0xFF屏蔽一个char,它可能仍然是符号扩展的,因为此时表达式仍然是一个char。它将是最好执行
static_cast()
@OliverD:考虑到
0xFF
的类型是
int
,它将对扩展
数据[…]进行签名
在掩码操作之前,只是为了使用and摆脱符号扩展。这是一个更一般的问题,但感谢您的努力。从技术上讲,这不会调用未定义的行为(从您以前没有编写过的union元素读取)?大多数编译器确实对此有特殊的例外,但可能仍然需要真正的一致性,特别是如果需要在广泛的平台上进行移植(谁知道什么时候会有一个编译器不支持这一点)。@Grizzly不确定我是否明白。此代码从流中读取并写入联合国