我在浏览有关cppreference(https://en.cppreference.com/w/c/io/fprintf)的printf文档时,发现使用z
修饰符和d
说明符时,该类型被列为“有符号{{ 1}}”。这让我感到好奇,所以我调查了为什么不使用size_t
只是为了发现ssize_t
是POSIX类型而不是标准类型。那么,这是什么类型的期望呢?寻找签名的ssize_t
类型时,我找不到ssize_t
以外的任何内容。
编辑:为澄清起见,我问我将使用哪种数据类型来表示签名的size_t
答案 0 :(得分:4)
“符号size_t
”的确切类型是实现定义的,并且是AFAIK,没有标准的方法来获取类型。因此,我看不到可移植地使用%zd
的方法。在大多数平台上,ptrdiff_t
应该是size_t
的签名版本,但这不能保证。实际上,t
有一个ptrdiff_t
格式修饰符,它也可以与u
这样的%tu
修饰符一起使用,表示“无符号ptrdiff_t
”。我认为这些组合仅出于完整性考虑,没有实际用途。
答案 1 :(得分:4)
术语“签名size_t
”是非正式使用的,并且未出现在语言标准中。实际上,如果您尝试在C代码中使用它,那将是语法错误。
C标准规定z
长度修饰符:
指定以下
d
,i
,o
, { {1}} ,u
或x
转换说明符 适用于X
或相应的带符号整数类型参数; 或以下size_t
转换说明符适用于指向 与n
参数相对应的带符号整数类型。
没有可移植的方法来确定相应的带符号整数类型是什么。即使是特定于POSIX的size_t
类型(在ssize_t
中定义)也未指定为与<sys/types.h>
对应的带符号类型。就像chux在评论中指出的那样,在某些实现中,size_t
比ssize_t
宽是有意义的,因此它可以表示直到size_t
的所有值(当然,加上,负值)。
实际上,SIZE_MAX
通常是预定义的无符号整数类型size_t
,unsigned int
或unsigned long int
和unsigned long long int
中的一种的typedef然后分别需要类型为%zd
,int
或long int
的参数。 long long int
也可能是根据某些扩展整数类型定义的。
我的猜测是,该标准的作者根本不想花费精力指定size_t
长度修饰符仅适用于带符号的类型。这样做会增加复杂性,却没有真正的好处。如果您使用的是符合POSIX的实现,则可以可能使用z
来打印类型为%zd
的值。
ssize_t
并没有可移植的用途,但是将其放在%zd
中是无害的,而且可能比不在那里使用容易。