我正在写一个程序,需要序列化一个二进制文件的小(最多16位)有符号整数。作为其中的一部分,我需要编写一个可以将整数分成两个字节的函数和另一个可以将这对字节转换回原始整数的函数。如何使用Lua将一对字节转换为带符号的16位整数?
是来到我的脑海里的第一个想法是类似的解决这个问题我将如何解决它为C:
function dump_i16(n)
assert (-0x8000 <= n and n < 0x8000) -- 16 bit
local b1 = (n >> 8) & 0xff
local b2 = (n >> 0) & 0xff
return b1, b2
end
function read_i16(b1, b2)
assert (0 <= b1 and b1 <= 0xff) -- 8 bit
assert (0 <= b2 and b2 <= 0xff) -- 8 bit
return (b1 << 8) | (b2 << 0)
end
但是,这些功能在负数中断,因为Lua的整数居然有64位,我我只保留低16位:
-- Positive numbers are OK
print(read_i16(dump_i16(17))) -- 17
print(read_i16(dump_i16(42))) -- 42
-- Negative numbers don't round trip.
print(read_i16(dump_i16(-1))) -- 65535 = 2^16 - 1
print(read_i16(dump_i16(-20))) -- 65516 = 2^16 - 20
什么会改变我的read_i16
功能,所以它可以正确处理负数干净的方式?
如果可能的话,我宁愿使用纯粹的Lua 5.3来做到这一点,而不必写下C代码。
你的dump_i16正在生成无符号值[0,256],所以它总是会失败你的断言 – Moop
你说'read_i16(dump_i16(-20)== 65516'和'65516 == 2^16 -20'。你为什么不从结果中减去'2^16'? – siffiejoe
@ Mooop:你说得对。我应该在半夜编辑它们之前进行测试... – hugomg