在uint128_t整数的上下文中对hexstring进行操作

标准Linux库函数strtoull是64位。

是否存在针对在uint128_t整数上运行的Linux x86_64环境的strtoX familyfunction的实现?

可能的原型:

 uint128_t strtoulll(const char *nptr, char **endptr, int base); 

另外,如何使用printf / sprintf打印uint128_t整数?

Solutions Collecting From Web of "在uint128_t整数的上下文中对hexstring进行操作"

作为标准,没有类型uint128_t 。 仅在J.5.6中 , __int128类型被称为“通用扩展名”,但仍不属于官方标准(列出的类型明显是有符号的,而不是无符号的)。

请注意, strtoull和家庭是标准的一部分,而不是Linux(无论“Linux”是什么意思)。

所以:没有标准的转换方式,也没有printf。

据我所知,在C11标准中没有uint128_t类型。
GCC有一个内置的类型__uint128_t ,但是printfstrtoull (标准函数)都不支持这种类型。

你可以找一些bigint库C

我已经写了一个strtoulll函数,应该像标准strtoull除了扩大返回类型。 我还写了一个非常非常简单的 sprint_uint128t函数, sprint_uint128t 128位无符号数字的十进制表示以相反的顺序打印到字符串中。 这只是因为我不喜欢像克隆实现一个完整的printf 。 反转字符串将有助于跟踪零/空格和其他格式的东西。
只有十进制版本是提供的,因为十六进制/二进制可以用标准的格式化说明符和八进制模拟很容易…八进制128位数字?

使用此代码需要您自担风险。 另外,我喜欢坏风格的C代码

这是非常糟糕的风格的代码。 开始者不应该复制粘贴,而是将其全部写入SCRATCH

 #include <stdio.h> #include <inttypes.h> #include <ctype.h> #include <errno.h> __uint128_t strtoulll(const char *nptr, char **endptr, int base) { int cbase = base ? base : 10; __uint128_t result = 0, tmp; int negate = 0, c, error=EINVAL; if (base < 0 || base > 36) goto error; while (isspace(*nptr++)); nptr--; if (*nptr == '-' || *nptr == '+') { negate = *nptr^'+'; nptr++; } if (*nptr == '0' && base == 0) { cbase = 8; nptr++; if (*nptr == 'x') { cbase = 16; nptr++; } } while (nptr) { c = *nptr-0x30; c = c < 10 ? c : c-7; c = c < 36 ? c : c-0x20; if (c < 0 || c >= cbase) goto error_setptr; error = 0; tmp = result*cbase + c; if ((tmp-c)/cbase != result) { error = ERANGE; goto error; } result = tmp; nptr++; } result = negate ? -result : result; error_setptr: if (endptr) *endptr = (char*)nptr; error: errno = error; return result; } void sprint_uint128(__uint128_t v, char* str) { int c; do { c = v % 10; v = v / 10; *str++ = c+'0'; } while (v); *str = 0; } int main() { __uint128_t t; unsigned long long l, h; int e; char* p; char buf[100]; t = strtoulll(" 340282366920938463463374607431768211455", &p, 0); e = errno; l = t & 0xffffffffffffffffULL; h = t >> 64; printf("Hex value %llx%016llx\nerr %d\nfirst unrecog char %d(%c)\nERANGE=%d, EINVAL=%d\n", l, h, e, *p, *p, ERANGE, EINVAL); sprint_uint128(t, buf); printf("\n\nPrinted dec reversed %s\n", buf); return 0; } 

当然这只适用于GCC。

注意任何想法在C更好的128位溢出检查?

重新思考我的问题后,我出来了这个答案。

gcc info:gcc版本4.9.1(Ubuntu 4.9.1-16ubuntu6)

目标:x86_64-linux-gnu

编译时使用:gcc -o / without标志

 #include <stdio.h> #include <string.h> #include <inttypes.h> #include <ctype.h> #include <errno.h> typedef __uint128_t uint128_t; typedef __uint64_t uint64_t; typedef __uint8_t uint8_t; const char *hex = "ffffffffffffffff0000000000000000"; uint8_t ascii2hex( char s ) { uint8_t r = 0xf; if( (s >= 48) && (s <= 57) ) r = s - 48; else if( (s >= 65) && ( s <= 70) ) r = s - 55; else if( (s >= 97) && (s <= 102) ) r = s - 87; return r; } uint128_t hex_strtoulll(const char *nptr, int len) { int i; uint128_t r = 0, p; for(i = len; i >= 0; i--) { p = (uint128_t)ascii2hex(*(nptr + i)); p = p << ((len - i) << 2); r |= p; } return r; } int printf_uint128_t(uint128_t x) { return printf("%016"PRIx64"%016"PRIx64"\n",(uint64_t)(x>>64),(uint64_t)x); } int main(int argc, char **argv) { uint128_t x = hex_strtoulll(hex, strlen(hex) - 1); uint128_t a = 0xffffffffffffffff; uint128_t b = 0xf; uint128_t c = a * b; printf_uint128_t(x); printf_uint128_t(c); printf_uint128_t(x - (c)); return 0; } 

我唯一的问题是,为什么我不能直接加载uint128_t的值? 出现此消息:警告:整数常量对于其类型来说太大。 警告消息在uint128_t值为2 ^ 64 – 1以上时为真。

  uint128_t x = 0xfffffffffffffffffffffffffffffff; sizeof(uint128_t) == 16 

而这按预期工作:

  uint128_t x = -1;