在C语言中如何存储int64_t类型相乘结果的低64位?并实现指定imull函数(禁止使用GCC内置函数)
关于C语言int64_t相乘低64位存储的解决方案
嘿,先直接给你答案:当然有办法搞定!而且完全不用依赖GCC内置函数,用标准C就能实现。另外顺便说一句,其实很多时候你直接写int64_t乘法,编译器会自动保留低64位,但因为C标准里有符号整数溢出属于未定义行为,所以严格来说还是用标准方法实现更稳妥。
下面是你要的imull函数的完整实现,我会一步步解释清楚:
函数实现(无编译器依赖)
核心思路是把64位整数拆成高32位和低32位,用32位乘法模拟64位乘法,手动计算出低64位结果,完全符合C标准:
#include <stdint.h> void imull(int64_t a, int64_t b, int64_t *res) { // 将两个64位整数拆分为高32位和低32位(用无符号类型避免符号扩展问题) uint32_t a_high = (uint32_t)(a >> 32); uint32_t a_low = (uint32_t)a; uint32_t b_high = (uint32_t)(b >> 32); uint32_t b_low = (uint32_t)b; // 计算四个32x32的乘法,每个结果都是64位(对应展开后的四个项) uint64_t mul_low_low = (uint64_t)a_low * b_low; uint64_t mul_low_high = (uint64_t)a_low * b_high; uint64_t mul_high_low = (uint64_t)a_high * b_low; // mul_high_high只会影响结果的高64位,这里我们不需要管它 // 计算低64位:mul_low_low的全部64位 + mul_low_high的低32位左移32 + mul_high_low的低32位左移32 uint64_t total_low = mul_low_low + ((mul_low_high & 0xFFFFFFFFULL) << 32) + ((mul_high_low & 0xFFFFFFFFULL) << 32); // 把无符号的64位结果转成int64_t,就是我们要的低64位 *res = (int64_t)total_low; }
代码逻辑说明
- 拆分整数:用
uint32_t来存拆分后的高/低32位,这样做乘法的时候不会因为符号位扩展导致错误。 - 分步乘法:把
a*b展开成(a_high*2^32 + a_low)*(b_high*2^32 + b_low),四个乘法项里,只有前三个会影响低64位,第四个a_high*b_high的结果只会出现在高64位,所以我们可以忽略它。 - 合并结果:把三个影响低64位的项加起来,就得到了最终的低64位结果——这里的加法即使有进位也没关系,因为我们只需要低64位,进位会自动被截断(或者说,进位本来就是高64位的部分,我们不需要)。
额外提示
如果你只是图省事,在大多数编译器(比如GCC、Clang、MSVC)上直接写*res = a * b;也能得到正确的低64位结果,但因为C标准明确规定有符号整数溢出是未定义行为,所以这种写法在严格场景下不推荐。上面的拆分方法是完全可移植的,不管什么平台什么编译器都能正常工作。
内容的提问来源于stack exchange,提问作者stedev
相关产品推荐
相关产品推荐

