将uint32_t十六进制值的一部分拆分为C ++中的较小部分

时间:2017-04-30 21:25:01

标签: c++ hex midi uint32-t

我有一个uint32_t如下:

uint32_t midiData=0x9FCC00;

我需要将这个uint32_t分成更小的部分,以便9成为它自己的实体,F成为它自己的实体,CC成为它自己的实体。如果你想知道我在做什么,我试图分解MIDI信息的各个部分,以便在我的程序中更容易管理。

我找到了this solution,但问题是我不知道如何将它应用到CC部分,并且我不确定此方法是否适用于C ++。

这是我到目前为止所做的:

uint32_t midiData=0x9FCC00;

uint32_t status = 0x0FFFFF & midiData; // Retrieve 9
uint32_t channel = (0xF0FFFF & midiData)>>4; //Retrieve F
uint32_t note = (0xFF00FF & midiData) >> 8; //Retrieve CC

这对C ++是否正确?我问的原因是因为我之前从未使用过C ++,并且使用了>和<一直困惑我(因此我倾向于避免它)。

3 个答案:

答案 0 :(得分:1)

您也可以在C ++中使用位移运算符>>和位屏蔽运算符&。 但是,如何使用它有一些问题:

运算符v1 & v2根据v1v2中设置的位构建一个数字,例如,0x12 & 0xF0给出0x10 ,而不是0x02。此外,位移运算符取位数,十六进制数中的单个数字(通常称为半字节)由4位(0x0..0xF需要4位)组成。因此,如果您有0x12并希望获得0x01,则必须撰写0x12 >>4。 因此,你的转变也需要调整:

#define BITS_OF_A_NIBBLE 4

unsigned char status = (midiData & 0x00F00000) >> (5*BITS_OF_A_NIBBLE);
unsigned char channel = (midiData & 0x000F0000) >> (4*BITS_OF_A_NIBBLE);
unsigned char note = (midiData & 0x0000FF00) >> (2*BITS_OF_A_NIBBLE);
unsigned char theRest = (midiData & 0x000000FF);

答案 1 :(得分:0)

你在某种程度上倒退了。

在布尔逻辑中(&是按位-AND),与0的ANDing将排除它。知道二进制中的F1111二进制,0x9FCC00 & 0x0FFFFF之类的行将为您提供除9之外的所有十六进制数字,与您想要的相反。

所以,状态:

uint32_t status = 0xF000000 & midiData; // Retrieve 9

实际上,这会给你0x900000。如果你想要0x9(也是十进制的9),你需要将结果进行位移。

现在,正确的bitshift运算符(例如,X>> 4)意味着向右移动X 4位;除以16.即4位,而不是4位十六进制数字。 1个十六进制数= = 4位,所以从0x900000得到9,你需要0x900000 >> 20

所以,把它们放在一起,得到9的状态:

uint32_t status = (0xF000000 & midiData) >> 20;

类似的过程将为您提供所需的剩余值。

答案 2 :(得分:0)

一般情况下,我建议首先进行转移,然后再进行掩码 - 它不易出错:

uint8_t cmd = (midiData >> 16) & 0xff;
uint8_t note = (midiData >> 8) & 0x7f;     // MSB can't be set
uint8_t velocity = (midiData >> 0) & 0x7f; // ditto

然后拆分cmd变量:

uint8_t status = (cmd & 0xf0);             // range 0x00 .. 0xf0
uint8_t channel = (cmd & 0x0f);            // range 0 .. 15

我个人不会费心将status值映射回0 ... 15的范围 - 通常可以理解,例如0x90是“注释”,而不是普通值9