首页 > 解决方案 > 为什么存在 printf 的 hh 和 h 长度修饰符?

问题描述

在可变参数函数中,会发生默认参数提升。

6.5.2.2.6 如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将具有类型的参数float提升为double。这些被称为默认参数提升。[...]

6.5.2.2.7 [...] 函数原型声明器中的省略号符号导致参数类型转换在最后声明的参数之后停止。默认参数提升是在尾随参数上执行的。

所以,

signed char c = 123;
int         i = 123;
float       f = 123;
double      d = 123;

printf("%d\n", i);   // ok
printf("%d\n", c);   // ok, even though %d expects int.
printf("%f\n", d);   // ok
printf("%f\n", f);   // ok, even though %f expects double.

那么为什么( ) 和( )有一个printf长度修饰符呢?charhhshorth


部分编号参考 N2176。

标签: cprintfvariadic-functionsinteger-promotion

解决方案


考虑这个例子:

#include <stdio.h>
int main(void)
{
    unsigned short x = 32770;
    printf("%d\n", x) ;  // (1)
    printf("%u\n", x) ;  // (2)
}

在典型的 16 位实现中,默认参数提升unsigned shortunsigned int,而在典型的 32 位实现中,unsigned short变为int.

所以在 16 位系统上,(1) 是 UB,(2) 是正确的,但在 32 位系统上,(1) 是正确的,(2) 可以争论是正确还是 UB。

用于%hu打印x适用于所有系统,您不必考虑这些问题。

可以为char具有sizeof(int) == 1.


推荐阅读