如何在`printf()`中使用“zd”说明符?

寻找有关使用printf() "zd"说明。

当然,以下对于C99及更高版本是正确的。

 void print_size(size_t sz) { printf("%zu\n", sz); } 

C规范似乎允许printf("%zd\n", sz)取决于它的读取方式:

7.21.6.1 fprintf函数

z指定以下diouxX转换说明符适用于size_t或相应的带符号整数类型参数; 或者后面的n转换说明符适用于指向与size_t参数对应的有符号整数类型的指针。 C11dr§7.21.6.17

这应该被解读为

  1. z指定以下d …转换说明符适用于size_t或相应的带符号整数类型参数…”(两种类型)和“ z指定后续u …转换说明符适用于size_t或对应的有符号整数类型参数……“(两种类型)

要么

  1. z指定以下d …转换说明符适用于相应的有符号整数类型参数…”(仅限带符号类型)和“ z指定后续u …转换说明符适用于size_t ”(无符号类型)只要)。

我一直在使用#2定义,但现在不太确定。

哪个是正确的,1,2或其他什么?

如果#2是正确的,那么可以使用"%zd"的类型的示例是什么?

具有"%zd"格式的printf与无符号类型size_t对应的signed类型的参数。

标准C不提供此类型的名称或确定其类型的好方法。 例如,如果size_tunsigned long的typedef,则"%zd"需要long类型的参数,但这不是可移植的假设。

该标准要求相应的有符号和无符号类型对两种类型中可表示的非负值使用相同的表示。 一个脚注说这意味着它们可以作为函数参数互换。 所以这:

 size_t s = 42; printf("s = %zd\n", s); 

应该工作,并应打印“42”。 它将解释无符号类型size_t的值42 ,就好像它是相应的有符号类型一样。 但实际上没有充分的理由这样做,因为"%zu"也是正确且定义明确的,而不需要使用其他语言规则。 并且"%zu"适用于size_t类型的所有值,包括相应签名类型范围之外的值。

最后,POSIX在头文件定义了一个类型ssize_t 。 虽然POSIX没有明确说明,但大概ssize_t将是与size_t对应的签名类型。 因此,如果您正在编写特定于POSIX的代码, "%zd" (可能)是打印ssize_t类型值的正确格式。

根据我所做的小测试,“zd”总是正确的,但“zu”不适用于负数。

测试代码:

  #include  int main (void) { int i; size_t uzs = 1; ssize_t zs = -1; for ( i= 0; i<5 ;i++, uzs <<= 16,zs <<= 16 ) { printf ("%zu\t", uzs); /*true*/ printf ("%zd\t", uzs); /*true*/ printf ("%zu\t", zs); /* false*/ printf ("%zd\n", zs); /*true*/ } return 0; }