除了%hn%hhn(其中hhh指定pointed-to对象的大小)之外,printf格式说明符的hhh修饰符的意义是什么?

由于标准要求应用于可变函数的默认升级,不可能将类型charshort(或其任何有符号/无符号变体)的参数传递给printf.

根据7.19.6.1(7),h修改量:

以下d、i、o、u、x或x转换规范适用于

如果参数实际上是类型shortunsigned short,那么升级到int,然后再转换回shortunsigned short,将产生与升级到int相同的value,而不进行任何转换.因此,对于类型shortunsigned short的参数,%d%u等应该给出与%hd%hu等相同的结果(对于char类型和hh也一样).

据我所知,hhh修饰符可能有用的唯一情况是参数传递给它的int超出了shortunsigned short的范围,例如

printf("%hu", 0x10000);

但我的理解是,像这样传递错误的类型会导致未定义的行为,因此您不能期望它打印0.

我见过的一个实际 case 是这样的代码:

char c = 0xf0;
printf("%hhx", c);

作者期望它打印f0,尽管实现具有签名的纯char类型(在这种情况下,printf("%x", c)将打印fffffff0或类似类型).但是,这样的期望有根据吗?

(注意:实际情况是,原来的类型是char,它被提升为int,然后转换回unsigned char而不是char,从而更改了打印的值.但是该标准是否规定了此行为,或者它是损坏的软件可能依赖的实现细节吗?)

推荐答案

一个可能的原因是:在格式化输入函数中使用这些修饰符是对称的吗?我知道这不是绝对必要的,但也许这是有价值的?

尽管他们没有提到the C99 Rationale document中"h"和"hh"修饰符的对称性的重要性,但委员会确实提到了它作为fscanf()支持"%p"转换说明符的考虑因素(尽管这在C99中并不 fresh -C90中支持"%p"):

C89中添加了带有%p的输入指针转换,尽管这显然有风险,因为它与fprintf对称.

在关于fprintf()的小节中,C99基本原理文档确实讨论了添加了"hh",但只是让读者参考fscanf()小节:

C99中添加了%hh和%ll长度改进剂(见§7.19.6.2).

我知道这是一条细线,但我还是在猜测,所以我想我会给出任何可能的论点.

此外,为了完整起见,"h"修饰符在最初的C89标准中-即使由于现有的广泛使用而不是严格必要的,即使可能没有使用该修饰符的技术要求,它也会存在.

C++相关问答推荐

Apple Libm的罪恶功能

常数函数指针优化

标准的C17标准是用括号将参数包装在函数声明中吗

手动矢量化性能差异较大

如何创建由符号组成的垂直结果图形?

从组播组地址了解收到的数据包长度

为什么在C中二维字符数组会有这样的行为?

C编译器是否遵循restrict的正式定义?

_泛型控制表达式涉及数组碰撞警告的L值转换错误?

文件权限为0666,但即使以超级用户身份也无法打开

如何在ASM中访问C struct 成员

Cairo STM32MP1 cairo_Surface_WRITE_TO_PNG始终返回CAROLIO_STATUS_WRITE_ERROR

当b是无符号字符时,int a=(b<;<;2)>;>;2;和int a=b&;0x3F;之间有什么区别?

用C++初始化局部数组变量

try 判断长整数是否为素数

在C中使用字符串时是否不需要内存分配?

我错误地修复了一个错误,想了解原因

我的代码可以与一个编译器一起使用,但不能与其他编译器一起使用

C struct 中的冒泡排序

这些表达式是否涉及 C 中定义的复合文字?