Шестнадцатеричное значение можно трактовать напрямую как целое число. Целые числа 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]
Для без перекрытия смежные поля, вы можете сделать это вместо этого:
# 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
Значения в строках являются общими значениями / шириной поля: %033lb
означает формат как 33 di git двоичное значение (101111010111100000001100011010001
в вашем примере), а %3b
означает анализ двоичного значения 3 di git в этой точке. (К сожалению, мы не можем сделать это намного более читаемым, так как между спецификаторами scan
не должно быть пробелов, поскольку во входных данных, которые мы только что сгенерировали, нет пробелов.)