在下面的示例代码中,printf如何知道uint8_t应该打印的大小,而上述格式只是“0x%x”而passd类型是uint32_t? printf怎么知道在第一次调用时它必须打印4个字节而第二次调用它必须只打印1个字节?
uint32_t X = 0xAABBCCDD;
printf("uint32_t 0x%x\n", (uint32_t) X);
printf("uint8_t 0x%x\n", (uint8_t) X);
输出
uint32_t 0xaabbccdd
uint8_t 0xdd
答案 0 :(得分:7)
它不知道。在这两种情况下,由于默认参数促销,您提供printf
[unsigned] int
。您的代码等同于: 1
printf("uint32_t 0x%x\n", (unsigned int)(uint32_t) X);
printf("uint8_t 0x%x\n", (int)(uint8_t) X);
促销规则是:
[6.3.1.1] 如果
int
可以表示原始类型[...]的所有值,则该值将转换为int
;否则,它将转换为unsigned int
。
此时printf
遵循的唯一规则是不打印前导零。
请注意,将签名的int
映射到%x
在技术上是未定义的行为。
<小时/> 1。我假设你在这里有32位
int
。
答案 1 :(得分:2)
在
printf("uint8_t 0x%x\n", (uint8_t) X);
uint8_t
绝对是低于int
的排名类型,因此uint8_t
将提升为int
,"%x"
将有效。
//potentially invokes UB depending on platform
printf("uint32_t 0x%x\n", (uint32_t) X);
是不可移植的代码。从理论上讲,您不知道实际类型uint32_t
是什么,因此您应该使用PRIx32
中的inttypes.h
宏。为了保持一致性/简单性,您也可以PRIx8
使用uint8_t
。
#include <inttypes.h>
#include <stdio.h>
int main()
{
uint32_t X = 0xAABBCCDD;
printf("uint8_t 0x%" PRIx8 "\n", (uint8_t) X);
printf("uint32_t 0x%" PRIx32 "\n", (uint32_t) X);
}