将十六进制字符串解码为 4 个部分,映射到值的二进制映射

Decoding a hex string into 4 pieces that maps to a binary map of values

我正在尝试解码一个所谓的十六进制字符串。在 MS SQL 服务器 (11.0.2100) 中,数据的类型为 char(8).

手册中没有明确的数据解码方法,但它记录了数据包含的内容:

Given a hex string ie. 0001003F with a length of 4. The lower byte is on the right, the higher byte is on the left. For each of the 4 'bytes' a reference table that maps a 'bit' to a certain truthy value was given. A bit order is also given having the bit 0 or the bit in right most being the 1st bit, ..., etc.

table 看起来像这样:

第一 'byte':

|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 个 tables 之后还有 3 个 'byte's ...,这 4 个 'byte's 中的每一个都应该有 8 个相等数量的 'bits')

我认为解码此数据的方法是将十六进制字符串拆分为 4 个部分,并将它们转换为宽度固定为 8 的二进制字符串。

PHP中,以十六进制'0001003F'为例,第一个字节是'3F',转换为二进制,0011 1111(space 为清楚起见)。然后,推断第一个字节的值为:

'state foo is on', 'in state bar', ..., 'not in state bazz'.

我也试过:hex2bin("0001003F") 但它输出 strin(4) " # ".

这是解码此数据的正确方法吗?

(标签有误请见谅)

因为 4 个字节适合 integer type on almost all platforms (32-bit and higher), you can convert the hex string to integer, then use the bitwise operators 的存储以检查是否设置了特定位:

$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 function. The loop iterates bit numbers in range [0;31] (starting from the least significant bit). The (1 << $bit) expression is the value 1 shifted to the left by $bit bits. Thus, if bit number $bit is set, then the result of the bitwise AND operation is a non-zero integer. The result is cast to boolean类型的帮助下将十六进制字符串$hex_str转换为整数$flags以产生1,如果结果不为零,和 0 否则。

很容易看出,您可以使用单个按位 AND 操作来测试多个位,例如:

// 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