这可能是一个非常愚蠢的问题,但是为什么在从BCD值转换为整数时,在按位操作中使用0xF。我知道0xF代表类似0x15的东西,在二进制中等于00010101。但是,为什么在上述程序中的位操作中使用这个特定的值?这个值的意义是什么?
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#define N_BCD_DIGITS 8
uint32_t packed_bcd(uint32_t packed_bcd);
int main(int argc, char *argv[]) {
for (int arg = 1; arg < argc; arg++) {
long l = strtol(argv[arg], NULL, 0);
assert(l >= 0 && l <= UINT32_MAX);
uint32_t packed_bcd_value = l;
printf("%lu\n", (unsigned long)packed_bcd(packed_bcd_value));
}
return 0;
}
// given a packed BCD encoded value between 0 .. 99999999
// return the corresponding integer
uint32_t packed_bcd(uint32_t packed_bcd_value) {
int result = 0;
for (int i = N_BCD_DIGITS - 1; i >= 0; i--) {
int decimal_digit = (packed_bcd_value >> (4 * i)) & 0xF;
assert(decimal_digit < 10);
result = result * 10 + decimal_digit;
}
return result;
}
2条答案
按热度按时间wsxa1bj11#
表达式
(packed_bcd_value >> (4 * i)) & 0xF
从BCD编码值中提取第i个数字(编号为0到7):值packed_bcd_value
被右移4 * i
比特,从具有较低数目比特的数字中移出比特,然后通过用掩码0b1111
屏蔽掉其他比特来提取低4比特,即:所有4个低位设置。0xF
是这个数字15
的十六进制表示。从C23开始,您可以使用0b1111
,但并非所有当前编译器都支持此语法。你可以通过给出以
0x
开头的命令行参数来测试你的程序,因为以0
为基数的strtol()
会将这些参数转换为十六进制:mgdq6dx12#
十六进制数中的一位表示半字节(4位)。
我知道0xF代表0x15,等于00010101
不,
0xf
在十进制中是15
(没有0x),在二进制中是0b1111
。当你用0xf(0b1111)与任何值进行二进制AND时,结果将包含这个数字的低4位的值。