假设我有这个:
uint8_t a[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
如果我:
printf("%lu", ((uint64_t*) a)[0]);
我会得到:
0x0102030405060708
如何使用非标准尺寸进行此操作?恩。 ((uint94_t) a)[0]
。
当然,没有uint94_t
,这就是我所要求的。如何读取非标准位数(甚至是字节,它也能为我完成工作)?
注意:我不关心printf的特定字符串(因此它可以解析非标准数量的位/字节)但是在数据类型中
答案 0 :(得分:2)
"%ul"
表示"%u"
(unsigned int),后跟字母"l"
。也许您打算"%lu"
(无符号长整数),但这两个对uint64_t
都不正确。
在inttypes.h
中找到了正确的说明符,它是"%" PRIu64
。
这也不会按照你的建议打印0x
,它会打印一个十进制表示。使用"%" PRIx64
表示十六进制表示(也不会打印前导0x
)。
继续,您的代码会导致undefined behaviour。根据严格别名规则,不允许使用uint64_t
类型的表达式来访问首先未写为uint64_t
或int64_t
的任何变量。
您可以通过使用正确类型的变量来避免严格别名规则,无论是在联合中还是其他方式,例如:
uint64_t x;
memcpy(&x, a, sizeof x);
printf("%" PRIu64 "\n", x);
您的编译器将对此进行优化,因此不要担心它效率低下或其他什么。
请注意,这是实现定义的的输出,因为编译器可以选择各种方式对uint64_t
的位进行排序。两个常见订单是 big-endian 和 little-endian 。
你问题的另一部分是关于其他整数类型。不幸的是,你坚持使用编译器提供的东西。很可能它没有提供uint94_t
。你必须推出自己的代码来实现你想要的。例如,您可以模拟96位大端:
uint8_t a[12] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C};
uint64_t x = 0, y = 0;
mempcy((unsigned char *)&x + 4, a, 4);
memcpy(&y, a+4, 8);
printf("%" PRIx64 "%" PRIx64 "\n", x, y);
当然你可以逐个字符地打印它。
答案 1 :(得分:0)
一点点谷歌搜索给了我答案...... 答案是位域!
typedef union {
__uint128_t i : 96;
} __attribute__((packed)) uint96_t;
printf("%ul", ((uint96_t*) a)[0]);