如何从 Tcl 中的十六进制值字符串中提取位字段并将它们输出为整数?
How to extract bit fields from a hex value string in Tcl and output them as integers?
我有表示十六进制值的字符串,其中包含多个不同位长度的字段。我必须提取它们并将它们打印在屏幕上。例如 0x17AF018D1 是一个 33 位十六进制值,其中位索引为 0 到 32;我需要提取位 0-5、6-7、8-21、22-30、31-32 中包含的数字。
我相信有多种方法可以做到这一点。什么是达到这英尺的最佳方法?
十六进制值可以直接作为整数处理。 Tcl 的整数实际上是任意精度值,但经过优化以有效地与主机系统的机器字长一起工作。 (Tcl 透明地为您处理细节。)
这意味着位域提取器可以像这样(假设是小端):
proc BitField {value from to} {
if {$from > $to} {
error "reversed bit field description"
}
# How many bits wide is the field?
set width [expr {$to - $from + 1}]
# Convert the width into a bit mask in the lowest bits
set mask [expr {(1 << $width) - 1}]
# Shift and mask the value to get the field
expr {($value >> $from) & $mask}
}
set abc 0x17AF018D1
puts [BitField $abc 0 5]
puts [BitField $abc 6 7]
puts [BitField $abc 8 21]
puts [BitField $abc 22 30]
# You are aware this overlaps?
puts [BitField $abc 30 32]
对于 non-overlapping 个连续的 字段,您可以改为这样做:
# Note that this is big endian as it is working with the string representation
scan [format "%033lb" $abc] "%3b%8b%14b%2b%6b" e d c b a
puts $a
puts $b
puts $c
puts $d
puts $e
字符串中的值是整体 value/field 宽度:%033lb
表示格式为 33 位二进制值(在您的示例中为 101111010111100000001100011010001
),%3b
表示此时解析一个 3 位二进制值。 (不幸的是,我们无法提高可读性,因为 scan
说明符之间不能有空格,因为我们刚刚生成的输入数据中没有空格。)
我有表示十六进制值的字符串,其中包含多个不同位长度的字段。我必须提取它们并将它们打印在屏幕上。例如 0x17AF018D1 是一个 33 位十六进制值,其中位索引为 0 到 32;我需要提取位 0-5、6-7、8-21、22-30、31-32 中包含的数字。
我相信有多种方法可以做到这一点。什么是达到这英尺的最佳方法?
十六进制值可以直接作为整数处理。 Tcl 的整数实际上是任意精度值,但经过优化以有效地与主机系统的机器字长一起工作。 (Tcl 透明地为您处理细节。)
这意味着位域提取器可以像这样(假设是小端):
proc BitField {value from to} {
if {$from > $to} {
error "reversed bit field description"
}
# How many bits wide is the field?
set width [expr {$to - $from + 1}]
# Convert the width into a bit mask in the lowest bits
set mask [expr {(1 << $width) - 1}]
# Shift and mask the value to get the field
expr {($value >> $from) & $mask}
}
set abc 0x17AF018D1
puts [BitField $abc 0 5]
puts [BitField $abc 6 7]
puts [BitField $abc 8 21]
puts [BitField $abc 22 30]
# You are aware this overlaps?
puts [BitField $abc 30 32]
对于 non-overlapping 个连续的 字段,您可以改为这样做:
# Note that this is big endian as it is working with the string representation
scan [format "%033lb" $abc] "%3b%8b%14b%2b%6b" e d c b a
puts $a
puts $b
puts $c
puts $d
puts $e
字符串中的值是整体 value/field 宽度:%033lb
表示格式为 33 位二进制值(在您的示例中为 101111010111100000001100011010001
),%3b
表示此时解析一个 3 位二进制值。 (不幸的是,我们无法提高可读性,因为 scan
说明符之间不能有空格,因为我们刚刚生成的输入数据中没有空格。)