c - 为什么存在 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
长度修饰符呢?char
hh
short
h
部分编号参考 N2176。
解决方案
考虑这个例子:
#include <stdio.h>
int main(void)
{
unsigned short x = 32770;
printf("%d\n", x) ; // (1)
printf("%u\n", x) ; // (2)
}
在典型的 16 位实现中,默认参数提升unsigned short
为unsigned int
,而在典型的 32 位实现中,unsigned short
变为int
.
所以在 16 位系统上,(1) 是 UB,(2) 是正确的,但在 32 位系统上,(1) 是正确的,(2) 可以争论是正确还是 UB。
用于%hu
打印x
适用于所有系统,您不必考虑这些问题。
可以为char
具有sizeof(int) == 1
.
推荐阅读
- maven - 在我的 Web 服务器上创建自定义 Maven 存储库
- java - 当我们将应用程序部署为war文件时如何在itext 7转换器属性中设置baseUri
- javascript - 突破代码不起作用。不知道如何做数组
- c++ - 这是存储浮点数的二维动态数组的正确初始化吗?
- sql - 拆分日期范围中的总 datediff 天数不等于非拆分日期范围中的 datediff 天数,为什么?
- c# - 如何修复播放模式后检查器中缺少的音频按钮?
- google-bigquery - BigQuery 中的 Firebase 数据,什么是“stream_id”?
- c# - 使用 C#/C++ 包装器寻找可能的内存泄漏
- python - 在python中预测正弦波
- javascript - Mongoose findOne 将文档作为错误返回?