我试图解码一个十六进制字符串。MS SQL Server (11.0.2100)中的数据类型为char(8)
。
在手册中没有明确的解码数据的方法,但它记录了它所包含的内容:
给定一个十六进制字符串。长度为4的
0001003F
。低字节在右边,高的字节在左边。对于每一个4'bytes
'是一个将'bit'映射到某个真值的引用表价值被赋予。位顺序也被给定为位0或位在最右边是第1位,…等。
表是这样的:
"字节"1:
|Bit Order | Description | 1 | 0 | trigger |
|-----------|---------------|-------------------|-------------------|---------------|
|BIT0 | state foo | state foo is ON | State foo is OFF | high level |
|BIT1 | state bar | in state bar | not in state bar | high level |
| ...
|BIT7 | state bazz | in state bazz | not in state bazz | high level |
(接下来的3个其他'字节'的3个表…(4个字节中的每一个应该有8个相同数量的'位')
我认为解码该数据的方式是将十六进制字符串分成4部分,并将其转换为二进制字符串宽度固定为8。
在PHP
中,以十六进制' 0001003F
'为例,第一个字节是' 3F
',转换为二进制,0011 1111
(空格表示清晰)。然后,推断第一个字节的值为:
'state foo is on', 'in state bar', ..., 'not in state bazz'
.
我也尝试做:hex2bin("0001003F")
,但它输出strin(4) " # "
。
这是解码数据的正确方法吗?
(如果标签不正确,请原谅)
由于在几乎所有平台(32位及更高)上4字节适合整数类型的存储,因此您可以将十六进制字符串转换为整数,然后使用位运算符检查是否设置了特定位:
$hex_str = '0001003F';
$flags = base_convert($hex_str, 16, 10);
foreach (range(0, 31) as $bit) {
printf("Bit %d: %d'n", $bit, (bool) ($flags & (1 << $bit)));
}
输出Bit 0: 1
Bit 1: 1
Bit 2: 1
Bit 3: 1
Bit 4: 1
Bit 5: 1
Bit 6: 0
...
Bit 15: 0
Bit 16: 1
Bit 17: 0
...
Bit 31: 0
如果$bit
位设置为(1),则该位对应的状态为on
代码通过base_convert
函数将十六进制字符串$hex_str
转换为整数$flags
。循环迭代[0;31]
范围内的位数(从最低有效位开始)。(1 << $bit)
表达式是1
的值左移了$bit
位。因此,如果设置了位号$bit
,则按位和运算的结果是一个非零整数。结果被强制转换为布尔类型以产生1
,如果结果不为零,则产生0
。
很容易看出,您可以使用单个按位和操作来测试多个位,例如:
// Check if at least one of three bits is set, 3rd, 10th, or 11th
$mask = (1 << 3) | (1 << 10) | (1 << 11);
if ($flags & $mask)
printf("At least one of the bits from mask 0x%x is set'n", $mask);
输出At least one of the bits from mask 0xc08 is set