C printf函数如何知道传递的整数大小?

时间:2018-05-29 22:06:03

标签: c pointers printf variadic-functions

在下面的示例代码中,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

2 个答案:

答案 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);
}