[英]Why does printf's hh and h length modifiers exist?
在可變參數函數中,會發生默認參數提升。
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.
那么為什么有一個用於char
( hh
) 和short
( h
) 的printf
長度修飾符呢?
章節編號參見 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
適用於所有系統,您不必考慮這些問題。
可以為sizeof(int) == 1
系統上的char
構造一個類似的示例。
這是為了向后兼容。
在 C89 標准的草案版本中,使用%x
格式說明符打印有符號的int
、 short
或char
不是未定義的行為:
d, i, o, u, x, X int 參數轉換為有符號十進制( d 或 i )、無符號八進制( o )、無符號十進制( u )或無符號十六進制表示法( x 或 X ); 字母 abcdef 用於 x 轉換,字母 ABCDEF 用於 X 轉換。 精度指定出現的最小位數; 如果被轉換的值可以用更少的數字表示,它將用前導零擴展。 默認精度為 1。使用顯式精度為零的零值轉換的結果是沒有字符。
這似乎證明了預先標准化的 C,使用格式說明符(例如%x
表示有符號值)是一種現有做法,因此可能存在使用h
和hh
長度修飾符的預先存在的代碼庫。
如果沒有h
和hh
長度修飾符,如果使用簡單的%X
格式說明符打印,則位模式為0xFF
有signed char
值將在 32 位int
系統上打印為0xFFFFFFFF
。
特別是關於hh
說明符,它在 C99 中明確添加,以便利用stdint.h
/ inttypes.h
中所有默認固定大小類型的打印。 C99 使int_leastn_t
類型從 8 到 64 是強制性的,因此需要相應的格式說明符。
來自 C99 基本原理 5.10, §7.19.6.1 ( fprintf
):
%hh
和%ll
長度修飾符是在 C99 中添加的(參見 §7.19.6.2)。
§7.19.6.2 ( fscanf
):
C99 的一個新特性:在 C99 中添加了
hh
和ll
長度修飾符。ll
支持新的 long long int 類型。hh
增加了將字符類型與所有其他整數類型一樣對待的能力; 這對於在<inttypes.h>
中實現諸如SCNd8
宏很有用(參見 7.18)。
在 C99 之前,只有d
、 h
和l
用於打印整數類型。 例如,在 C99 中,傳統實現可以將inttypes.h
說明符定義為:
#define SCNi8 hh
#define SCNi16 h
#define SCNi32 d
#define SCNi64 ll
現在默認參數提升成為printf
/ scanf
實現的inttypes.h
,而不是inttypes.h
實現。
它們不是用於printf()
使用,而是用於scanf()
能夠使用對short
整數和char
整數的引用。 為了統一性和完整性,它們被printf()
函數接受,但它們是不可區分的,因為對於所有類型為short
和char
整數值的參數, printf()
的 vaarg 參數都被提升為int
。 所以它們在printf()
是等價的,但在scanf()
和朋友中不是。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.