源端 Lua4 本身没位运算,我这边补了一个 bit32(Lua5.2 那套名字),脚本里直接用 bit32.xxx()。
注意:Lua4 不支持 0x1234 这种十六进制字面量,写数字请用十进制。
1)新增函数一览(新增函数 / 作用)
| 新增函数 |
作用 |
bit32.band(...) |
按位与(支持多个参数) |
bit32.bor(...) |
按位或(支持多个参数) |
bit32.bxor(...) |
按位异或(支持多个参数) |
bit32.bnot(x) |
按位取反(32 位) |
bit32.btest(...) |
band(...) 结果是否非 0(返回布尔) |
bit32.lshift(x, n) |
左移 n 位(32 位截断) |
bit32.rshift(x, n) |
逻辑右移 n 位(高位补 0) |
bit32.arshift(x, n) |
算术右移 n 位(按符号扩展) |
bit32.lrotate(x, n) |
循环左移(rotate left) |
bit32.rrotate(x, n) |
循环右移(rotate right) |
bit32.extract(x, field [, width]) |
取位段:从 field 开始取 width 位 |
bit32.replace(x, v, field [, width]) |
替换位段:把 x 的某段替换成 v |
说明:全部运算按 32 位无符号处理,超出会自动截断到 0 ~ 2^32-1。
2)基础示例:AND/OR/XOR/NOT
-- 1) band:按位与
print(bit32.band(7, 3)) -- 7(111) & 3(011) = 3
-- 2) bor:按位或
print(bit32.bor(5, 2)) -- 5(101) | 2(010) = 7
-- 3) bxor:按位异或
print(bit32.bxor(6, 3)) -- 6(110) ^ 3(011) = 5
-- 4) bnot:按位取反(32位)
print(bit32.bnot(0)) -- 4294967295
3)btest:检测某些位是否存在(最常用)
local flags = 5 -- 二进制 0101
-- 判断第 0 位是否为 1(mask=1)
print(bit32.btest(flags, 1)) -- true
-- 判断第 1 位是否为 1(mask=2)
print(bit32.btest(flags, 2)) -- false
-- 判断第 2 位是否为 1(mask=4)
print(bit32.btest(flags, 4)) -- true
4)shift:左移 / 逻辑右移 / 算术右移
-- 左移:1 << 3 = 8
print(bit32.lshift(1, 3)) -- 8
-- 逻辑右移:8 >> 2 = 2
print(bit32.rshift(8, 2)) -- 2
-- 算术右移:主要用在“带符号意义”的右移
-- 例如把 0x80000000 当成负数的符号扩展(Lua4里别写0x,用十进制2147483648)
print(bit32.arshift(2147483648, 1)) -- 3221225472 (看起来像负数右移的效果)
rshift 永远补 0;arshift 会按最高位做符号扩展。
5)rotate:循环移位(转圈)
-- rrotate:把最低位转到最高位
print(bit32.rrotate(1, 1)) -- 2147483648
-- lrotate:把最高位转到最低位
print(bit32.lrotate(2147483648, 1)) -- 1
写 0x00000001 在 Lua4 里会语法错,直接写 1。
extract(x, field, width)
field:从第几位开始(0 起)
width:取多少位(默认 1)
-- 例:x = 13 (二进制 1101)
local x = 13
-- 取第0位(最低位),宽度1 -> 1
print(bit32.extract(x, 0, 1)) -- 1
-- 取第1位,宽度2(取bits[1..2])
print(bit32.extract(x, 1, 2)) -- 2 (1101 的 [01]?? 结果按位段算)
(实际用它最多是从标志位里抠某个字段值。)
7)replace:替换某段 bit(字段写入)
replace(x, v, field, width)
把 x 从 field 开始的 width 位替换为 v(只取 v 的低 width 位)
-- x=0,把第4位开始的3位写成 5(二进制101)
local x = 0
local y = bit32.replace(x, 5, 4, 3)
print(y) -- 5 << 4 = 80
8)Lua4 写法注意点(别踩坑)
-
Lua4 不支持 0x...
0x80000000 请写十进制 2147483648
-
参数必须是整数意义的 number
- 传 1.2 这种会报 “number has no integer representation”
-
所有结果都会截断到 32 位
- 超过 0xFFFFFFFF 会自动 mod 2^32
9)测试代码
print("=== band/bor/bxor/bnot (single + multi args) ===")
print(bit32.band(7, 3)) -- 3
print(bit32.band(255, 240, 15)) -- 0
print(bit32.bor(5, 2)) -- 7
print(bit32.bor(1, 2, 4, 8)) -- 15
print(bit32.bxor(6, 3)) -- 5
print(bit32.bxor(1, 2, 4)) -- 7
print(bit32.bnot(0)) -- 4294967295
print(bit32.bnot(4294967295)) -- 0
print("\n=== btest ===")
print(bit32.btest(5, 1)) -- true(通常打印 1)
print(bit32.btest(5, 2)) -- false(通常打印 nil)
print(bit32.btest(0, 1)) -- false(通常打印 nil)
print("\n=== shifts ===")
print(bit32.lshift(1, 3)) -- 8
print(bit32.lshift(1, 31)) -- 2147483648
print(bit32.lshift(1, 40)) -- 0 (>=32 位直接 0)
print(bit32.rshift(8, 2)) -- 2
print(bit32.rshift(2147483648, 31)) -- 1
print(bit32.rshift(1, 1)) -- 0
print(bit32.arshift(2147483648, 1)) -- 3221225472 (0xC0000000)
print(bit32.arshift(4294967295, 1)) -- 4294967295 (0xFFFFFFFF)
print("\n=== rotates ===")
print(bit32.lrotate(1, 1)) -- 2
print(bit32.lrotate(2147483648, 1)) -- 1
print(bit32.rrotate(1, 1)) -- 2147483648
print(bit32.rrotate(2, 1)) -- 1
print(bit32.rrotate(1, 0)) -- 1
print("\n=== extract/replace ===")
print(bit32.extract(240, 4, 4)) -- 15 (240 = 0xF0)
print(bit32.extract(240, 0, 4)) -- 0
print(bit32.extract(15, 0, 4)) -- 15
print(bit32.replace(0, 15, 4, 4)) -- 240
print(bit32.replace(255, 0, 4, 4)) -- 15 (255=0xFF -> 清掉高4位)
print(bit32.replace(240, 3, 0, 2)) -- 243 (0xF0 -> 0xF3)
输出结果:
=== band/bor/bxor/bnot (single + multi args) ===
3
0
7
15
5
7
4294967295
0
=== btest ===
1
nil
nil
=== shifts ===
8
2147483648
0
2
1
0
3221225472
4294967295
=== rotates ===
2
1
2147483648
1
1
=== extract/replace ===
15
0
15
240
15
243