位掩码以获取单个字节
Bitmasking to get individual bytes
我正在尝试遍历 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 似乎工作正常,但格式却不是。我正在寻找只包含字节值的打印语句,而不是现在的 uint64_t val。
我认为将掩码作为 uin64_t 会扰乱单字节值的打印,但我不确定如何修复它。我收到这样的反馈:
数据 [1] 字节 [1]: 0x1100
但想以如下形式获取我的数据:
数据[1] 字节[1]: 0x11
如果您想获得单字节值,最简单的方法是右移 data
而不是右移 mask
。正如@harold 正确提到的那样, 'oring' 带有 0xff 的字节没有意义。
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;
}
}
你显然至少有三个问题:
- 您在需要按位 "and" (
&
) 的地方使用按位 "or" (|
)。
- 您在需要
data
的 元素 的地方使用 data
。您的特定用途甚至不应该编译,因为指针不允许作为按位算术运算符的操作数。
- 您转移数据/屏蔽数据失败。
您还在对另一个答案的评论中声称,即使在更正这些错误之后,您得到的输出中也有许多前导零。我无法用 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));
}
}
这会移动数据以使其与掩码匹配,而不是将掩码移动到 select 数据,因为后者无论如何都需要移动结果。我假设正确运算符的索引和使用不需要进一步解释。
但是,还要注意字段描述符和演员表。 %02hhx
表示该字段将被零填充 (0
) 且宽度至少为两个字符 (2
)。相应的参数是一个无符号整数类型,以十六进制形式表示(x
),具体来说,它是一个unsigned char
(hh
)。相应的参数转换为 unsigned char
以匹配。
我正在尝试遍历 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 似乎工作正常,但格式却不是。我正在寻找只包含字节值的打印语句,而不是现在的 uint64_t val。 我认为将掩码作为 uin64_t 会扰乱单字节值的打印,但我不确定如何修复它。我收到这样的反馈: 数据 [1] 字节 [1]: 0x1100 但想以如下形式获取我的数据: 数据[1] 字节[1]: 0x11
如果您想获得单字节值,最简单的方法是右移 data
而不是右移 mask
。正如@harold 正确提到的那样, 'oring' 带有 0xff 的字节没有意义。
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;
}
}
你显然至少有三个问题:
- 您在需要按位 "and" (
&
) 的地方使用按位 "or" (|
)。 - 您在需要
data
的 元素 的地方使用data
。您的特定用途甚至不应该编译,因为指针不允许作为按位算术运算符的操作数。 - 您转移数据/屏蔽数据失败。
您还在对另一个答案的评论中声称,即使在更正这些错误之后,您得到的输出中也有许多前导零。我无法用 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));
}
}
这会移动数据以使其与掩码匹配,而不是将掩码移动到 select 数据,因为后者无论如何都需要移动结果。我假设正确运算符的索引和使用不需要进一步解释。
但是,还要注意字段描述符和演员表。 %02hhx
表示该字段将被零填充 (0
) 且宽度至少为两个字符 (2
)。相应的参数是一个无符号整数类型,以十六进制形式表示(x
),具体来说,它是一个unsigned char
(hh
)。相应的参数转换为 unsigned char
以匹配。