C语言中的12字节整数
我需要一个12字节或96位无符号整数来对它进行简单的算术运算。我尝试了以下方法,因为C中没有内置的数据类型C语言中的12字节整数,c,x86,arm,C,X86,Arm,我需要一个12字节或96位无符号整数来对它进行简单的算术运算。我尝试了以下方法,因为C中没有内置的数据类型 typedef struct { __uint128_t i:96; __uint128_t j:96; }; __uint128_t __add(__uint128_t a, __uint128_t b) { return a + b; } 但一些较旧版本的GCC编译器版本不支持这一点 因此,需要具有交叉编译支持的通用实现 根据这里提到的答案- 3个整数的数组,作为替
typedef struct
{
__uint128_t i:96;
__uint128_t j:96;
};
__uint128_t __add(__uint128_t a, __uint128_t b) { return a + b; }
但一些较旧版本的GCC编译器版本不支持这一点
因此,需要具有交叉编译支持的通用实现
根据这里提到的答案-
3个整数的数组,作为替代解决方案?怎么做
非常感谢任何进一步的帮助 如果需要使用通用解决方案,可以尝试创建包含64位整数和另一个32位整数的结构。然后重新定义一些需要执行的操作
一个经典的例子是struct timespec,它有两个整数,一个表示秒,一个表示纳秒。最简单的方法是使用uint128\t,除非它在您的平台上不可用,或者使用的额外存储不知何故对您是个问题 也就是说,您可以使用问题中提到的三个uint32的数组。但是你需要自己实现所有的基本算术运算,正如你所看到的,它会变得非常复杂!下面是一个刚刚实现的加法示例
#include <stdio.h>
#include <stdint.h>
typedef struct uint96_t
{
uint32_t value[3];
}uint96_t;
uint96_t add_uint96(uint96_t x, uint96_t y)
{
uint96_t result = {0};
unsigned int carry = 0;
int i = sizeof(x.value)/sizeof(x.value[0]);
/* Start from LSB */
while(i--)
{
uint64_t tmp = (uint64_t)x.value[i] + y.value[i] + carry;
result.value[i] = (uint32_t)tmp;
/* Remember the carry */
carry = tmp >> 32;
}
return result;
}
void print_uint96(char *str, uint96_t x)
{
printf("%s = %08x%08x%08x\r\n", str, x.value[0], x.value[1], x.value[2]);
}
int main(void)
{
uint96_t x = {0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
uint96_t y = {0x00, 0x00, 0x01};
uint96_t r = add_uint96(x, y);
print_uint96("x", x);
print_uint96("y", y);
print_uint96("result", r);
return 0;
}
在struct timespec的帮助下,我做了如下工作:
使用GMP多精度算术库怎么样?为什么需要96位整数并对其进行算术运算?您需要解决的真正问题是什么?如果需要存储纳秒值,则将整秒存储在64位整数中,将小数部分存储在32位整数中。这方面的算法并不难。这就是struct timespec在实际中所做的。您必须决定是否需要两个纳秒时间值之间的有符号值负间隔。处理符号位更为棘手,可能需要在64位中使用1位符号和63位大小字段,持续整秒钟。@Thulasivegalam,您需要交叉编译到哪个96位计算机。。。说真的,只需使用一个bigint库。@Lundin:像这样的多精度库是一个极大的不必要的膨胀。元数据本身(例如位数、空间量)将比数据成本高,并且由于不必要的条件,性能将下降。长双实浮点类型,通常映射为扩展精度浮点数字格式。实际属性未指定。它可以是x86扩展精度浮点格式80位,但在内存中通常是96位或128位(带填充字节)、非IEEE双精度128位、IEEE 754四精度浮点格式128位,或与双精度相同。有关详细信息,请参阅关于long double的文章。@Thulasivegalam:在某些针对x86-64的C实现中,long double是80位x87类型。e、 g.Linux/MacOS编译器。在Windows上,long double与64位double MSVC和gcc/clang/ICC Windows相同。您不太可能不想要数据的扩展精度FP。@Thulasivegalam如果您想要特定数量的存储,我认为浮点不是正确的方法。它可能涉及更复杂的问题,并且不能保证提供所需的精度位数。就像上面提到的Peter一样,平台之间的变量甚至比整数更大。顺便说一句,C11指定tv_nsec是一个有符号长的,所以是的,减法可以使其为负数,而不是换行为高无符号值。
struct timespec
__timespec_add (const struct timespec start,
const struct timespec end)
{
struct timespec sum;
sum.tv_sec = start.tv_sec + end.tv_sec;
sum.tv_nsec = start.tv_nsec + end.tv_nsec;
if (sum.tv_nsec >= 1000000000)
{
++sum.tv_sec;
sum.tv_nsec = sum.tv_nsec - 1000000000;
}
return sum;
}
struct timespec
__timespec_diff (const struct timespec start,
const struct timespec end)
{
struct timespec diff;
diff.tv_sec = start.tv_sec - end.tv_sec;
diff.tv_nsec = start.tv_nsec - end.tv_nsec;
if (diff.tv_nsec < 0)
{
--diff.tv_sec;
diff.tv_nsec = diff.tv_nsec + 1000000000;
}
return diff;
}