乘以非常大的十六进制数并在 C 中打印它们

Multiplying very large hex numbers and printing them in C

我想将 2 个非常大的十六进制数相乘并打印出来,例如:

28B2D48D74212E4F x 6734B42C025D5CF7 = 1068547cd3052bbe5688de35695b1239

因为我预计它是一个非常大的数字,所以我使用 unsigned long long int 输入:

unsigned long long int x = 0x28B2D48D74212E4F;   
unsigned long long int y = 0x6734B42C025D5CF7; 

并像这样打印乘法:

fprintf(stdout, "%llx\n",  x*y);

我得到的正好是预期结果的一半:

5688de35695b1239

为什么要把它截断到一半?有没有比unsigned long long更大的东西?

您要查找的响应不适合 64 位 unsigned long long,这是 64 位平台上的正常大小;乘法期间的任何多余部分都会溢出并丢弃。

较新版本的 GCC 在 64 位机器 和 __int128(和 unsigned __int128)上支持 128 位整数 ,这有效:

unsigned long long int x = 0x28B2D48D74212E4FULL;
unsigned long long int y = 0x6734B42C025D5CF7ULL;
unsigned __int128 xy = x * (unsigned __int128)y;

请注意,您必须将 xy 之一转换为更宽的类型,以便以 128 位完成乘法;否则,直到(截断的)64 位乘法之后才会提升到 128。

问题是,据我所知,printf() 没有办法轻松地做到这一点,所以你将不得不自己动手。

这里有一些合理的讨论:how to print __uint128_t number using gcc?

但这对我有用:

gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)

#include <stdio.h>

int main()
{
unsigned long long int x = 0x28B2D48D74212E4F;
unsigned long long int y = 0x6734B42C025D5CF7;
unsigned __int128 xy = x * (unsigned __int128)y;

    printf("Result = %016llx%016llx\n",
        (unsigned long long)( xy >> 64),
        (unsigned long long)( xy & 0xFFFFFFFFFFFFFFFFULL));

    return 0;

printf 中的转换很重要:否则 shifting/masking 是在 128 位标量中完成的,然后将这 128 位压入堆栈,但随后每个 %llx 期望64 位。

请注意,这完全取决于底层平台并且不可移植;肯定有一种方法可以使用各种#ifdefs 和 sizeofs 来使其更通用,但可能没有超级棒的方法可以使它在任何地方都有效。