Bitmasking获取单个字节

时间:2016-07-12 14:13:36

标签: c bitwise-operators bit-shift

我正在尝试浏览一个uint64_t的数组

即:

const uint64_t data[] =
{
    0x0000000000000000,
    0x1111111111111111,
    0x2322323232323232
}

由此我想遍历数组中的每个索引和每个索引,打印每个字节的值。我认为一个位掩码就是这样做的,但我不能说得对......到目前为止我有这个:

static const int indices = sizeof(data) / sizeof(uint64_t);
uint64_t mask;

for(int i= 0; i < indices; i++)
{
    mask = 0xff;
    for(int byte = 0; byte < 8; byte++)
    {
        printf("index[%d], byte[%d]: 0x%02x\n", i, byte, data | mask);
        mask = mask << 8;
        printf("mask: 0x%016lx\n", mask);
    }
}

我的输出与掩码一样。每个循环移位8位(1个字节)。然而,按位数据比较是愚蠢的。按位AND似乎工作正常,但格式不是。我正在寻找只保存字节值的print语句,而不是现在的uint64_t val。 我认为将掩码作为uin64_t会弄乱单字节值的打印,但我不确定如何修复它。我得到这样的反馈: data [1] byte [1]:0x1100 但希望以如下形式获取我的数据: data [1] byte [1]:0x11

2 个答案:

答案 0 :(得分:3)

你显然至少有三个问题:

  1. 您使用按位“或”(|),您想要按位“和”(&)。
  2. 您正在使用data您想要data元素。您的特定用途甚至不应该编译,因为指针不允许用于按位算术运算符的操作数。
  3. 您无法移动数据/屏蔽数据。
  4. 你还在另一个答案的评论中声称,即使纠正了这些错误,你也会获得许多前导零的输出。我不能用GCC复制那个结果,但我确实观察到字段描述符必须为参数指定正确的类型。您的参数是uint64_t,并且在大多数C系统中与unsigned int不对应,这是字段描述符x在未提供长度修饰符时所期望的。如果即使所有内容都正确匹配,也会显示额外的前导零,那么x的实现可能会输出所有字节的表示形式,而不会截断前导零。在这种情况下,您可以尝试将参数指定为(并且实际上使其成为)unsigned char

    把这些放在一起,你想要更像这样的东西:

    for (int i = 0; i < indices; i++)
    {
        for(int byte = 0; byte < 64; byte += 8)
        {
            printf("index[%d], byte[%d]: 0x%02hhx\n", i, byte,
                (unsigned char) ((data[i] >> byte) & 0xff));
        }
    }
    

    将数据移位以使其与掩码匹配,而不是移动掩码以选择数据,因为后者无论如何都需要移位结果。我假设索引和使用正确的运算符不需要进一步解释。

    但是,请注意字段描述符和强制转换。 %02hhx表示该字段为零填充(0)且至少两个字符宽(2)。相应的参数是无符号整数类型,以十六进制形式(x)表示,特别是unsigned charhh)。相应的参数将转换为unsigned char以匹配。

答案 1 :(得分:2)

如果您想要单字节值,最简单的方法是右移data而不是移位mask。正如@harold所提到的那样,使用0xff'oring'一个字节是没有意义的。

for(int i= 0; i < indices; i++)
{
    uint64_t val = data[i];
    for(int byte = 0; byte < 8; byte++)
    {
        printf("index[%d], byte[%d]: 0x%02x\n", i, byte, val & 0xff );
        val >>= 8;
    } 
}