如何实现溢出时取低64位的64位整数算术运算(+、-、*)?
实现符合128位运算取低64位的64位整数加减乘运算
完全可行。你的需求本质是让64位有符号整数运算溢出时,结果等效于先转换为128位有符号整数执行运算,取低64位后再转回64位有符号整数的结果,可通过以下两种方式实现,取决于编译器是否支持128位整数类型。
方法一:利用编译器原生128位整数支持
GCC、Clang等主流编译器都支持__int128(128位有符号整数)扩展类型,直接用它就能完成需求,代码简洁且高效:
加法
#include <stdint.h> int64_t safe_add(int64_t a, int64_t b) { return (int64_t)((__int128)a + (__int128)b); }
减法
int64_t safe_sub(int64_t a, int64_t b) { return (int64_t)((__int128)a - (__int128)b); }
乘法
int64_t safe_mul(int64_t a, int64_t b) { return (int64_t)((__int128)a * (__int128)b); }
编译器会自动将64位整数提升到128位运算,再截断低64位转回64位,完全符合要求,同时避免了有符号整数溢出的未定义行为。
方法二:无符号运算兼容方案(不依赖__int128)
如果需要兼容不支持__int128的编译器,可利用无符号整数运算的确定性环绕特性(溢出时自动取低64位),再将结果转回有符号整数,效果和128位运算取低64位一致:
加法
int64_t safe_add(int64_t a, int64_t b) { uint64_t ua = (uint64_t)a; uint64_t ub = (uint64_t)b; return (int64_t)(ua + ub); }
减法
int64_t safe_sub(int64_t a, int64_t b) { uint64_t ua = (uint64_t)a; uint64_t ub = (uint64_t)b; return (int64_t)(ua - ub); }
乘法(手动拆分计算)
乘法需手动拆分64位整数为32位段,通过32位运算组合出低64位结果:
int64_t safe_mul(int64_t a, int64_t b) { uint32_t ah = (uint32_t)(a >> 32); uint32_t al = (uint32_t)a; uint32_t bh = (uint32_t)(b >> 32); uint32_t bl = (uint32_t)b; uint64_t al_bl = (uint64_t)al * bl; uint64_t al_bh = (uint64_t)al * bh; uint64_t ah_bl = (uint64_t)ah * bl; // 累加各部分得到低64位,高32位的乘积部分不影响低64位结果 uint64_t res = al_bl + (al_bh << 32) + (ah_bl << 32); return (int64_t)res; }
关键说明
- 无符号整数运算的环绕行为是C标准明确规定的,因此上述兼容方案完全可移植,不会触发未定义行为。
- 将无符号运算结果转回有符号整数时,得到的就是128位有符号运算后低64位的符号解释,和需求完全匹配。
- 对于支持
__int128的平台,优先使用方法一,编译器会生成最优机器码(比如x86-64平台会直接利用mulq指令生成128位乘积,再截断低64位)。
内容的提问来源于stack exchange,提问作者Simd
相关产品推荐
相关产品推荐

