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

时间:2015-10-02 22:10:35

标签: c printf

正在寻找关于将"zd"printf()一起使用的说明。

当然,以下内容对于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或相应的有符号整数类型参数...”(两种类型)和“{{ 1}}指定以下z ...转换说明符适用于u或相应的带符号整数类型参数...“(两种类型)
  2. OR

    1. size_t指定以下z ...转换说明符适用于相应的有符号整数类型参数...”(仅限带符号类型)和“d指定以下z ...转换说明符适用于u“(仅限无符号类型)。
    2. 我一直在使用#2定义,但现在不太确定。

        

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

           

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

2 个答案:

答案 0 :(得分:14)

带有printf格式的

"%zd"需要与无符号类型size_t对应的带符号类型的参数。

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

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

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

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

最后,POSIX在标题<unistd.h><sys/types.h>中定义了类型ssize_t。虽然POSIX没有明确说明,但大概ssize_t将是与size_t对应的签名类型。 因此,如果您正在编写特定于POSIX的代码,"%zd"(可能)是打印ssize_t类型值的正确格式。

答案 1 :(得分:0)

根据我所做的小测试,&#34; zd&#34;总是如此,但是&#34; zu&#34;不要为负数工作。

测试代码:

  #include <stdio.h>
  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;
}