如何将 "zd" 说明符与 `printf()` 一起使用?
How to use "zd" specifier with `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
Specifies that a following d
, i
, o
, u
, x
, or X
conversion specifier applies to a size_t
or the corresponding signed integer type argument; or that a following n
conversion specifier applies to a pointer to a signed integer type corresponding to size_t
argument. C11dr §7.21.6.1 7
这个应该读作
- "
z
指定后面的 d
... 转换说明符适用于 size_t
或相应的有符号整数类型参数 ..."(两种类型)和 " z
指定后面的 u
... 转换说明符适用于 size_t
或相应的有符号整数类型参数 ...”(两种类型)
或
- "
z
指定后面的 d
... 转换说明符适用于相应的有符号整数类型参数 ..."(仅限有符号类型)和"z
指定以下 u
... 转换说明符适用于 size_t
"(仅限无符号类型)。
我一直在使用 #2 定义,但现在不太确定。
Which is correct, 1, 2, or something else?
If #2 is correct, what is an example of a type that can use "%zd"
?
根据我所做的小测试,"zd" 始终为真,但 "zu" 不适用于负数。
测试代码:
#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;
}
具有 "%zd"
格式的 printf
需要一个对应于无符号类型 size_t
.
的有符号类型的参数
标准 C 不提供此类型的名称或确定它是什么的好方法。例如,如果 size_t
是 unsigned long
的 typedef,那么 "%zd"
需要一个 long
类型的参数,但这不是一个可移植的假设。
标准要求相应的有符号和无符号类型对 non-negative 值使用相同的表示,这两种类型都可以表示。一个脚注说这意味着它们可以作为函数参数互换。所以这个:
size_t s = 42;
printf("s = %zd\n", s);
应该可以,并且应该打印“42”。它会将无符号类型 size_t
的值 42
解释为对应的有符号类型。但确实没有充分的理由这样做,因为 "%zu"
也是正确且定义明确的,无需诉诸其他语言规则。并且 "%zu"
适用于类型 size_t
的 所有 值,包括那些超出相应符号类型范围的值。
最后,POSIX在headers<unistd.h>
and <sys/types.h>
中定义了一个类型ssize_t
。尽管 POSIX 没有明确说明,但 ssize_t
很可能是 size_t
对应的签名类型。
因此,如果您正在编写 POSIX-specific 代码,"%zd"
(可能)是打印 ssize_t
.
类型值的正确格式
更新:POSIX explicitly says ssize_t
不一定是 size_t
的签名版本,所以这是不明智的编写假定它是的代码:
ssize_t
This is intended to be a signed analog of size_t
. The wording is such
that an implementation may either choose to use a longer type or
simply to use the signed version of the type that underlies size_t
.
All functions that return ssize_t
(read()
and write())
describe as
"implementation-defined" the result of an input exceeding {SSIZE_MAX
}.
It is recognized that some implementations might have int
s that are
smaller than size_t
. A conforming application would be constrained not
to perform I/O in pieces larger than {SSIZE_MAX
}, but a conforming
application using extensions would be able to use the full range if
the implementation provided an extended range, while still having a
single type-compatible interface. The symbols size_t
and ssize_t
are
also required in <unistd.h>
to minimize the changes needed for calls
to read()
and write()
. Implementors are reminded that it must be
possible to include both <sys/types.h>
and <unistd.h>
in the same
program (in either order) without error.
寻求有关将 "zd"
与 printf()
一起使用的说明。
当然,以下对于 C99 及更高版本是正确的。
void print_size(size_t sz) {
printf("%zu\n", sz);
}
C 规范 似乎 允许 printf("%zd\n", sz)
取决于它的阅读方式:
7.21.6.1 fprintf
函数
z
Specifies that a followingd
,i
,o
,u
,x
, orX
conversion specifier applies to asize_t
or the corresponding signed integer type argument; or that a followingn
conversion specifier applies to a pointer to a signed integer type corresponding tosize_t
argument. C11dr §7.21.6.1 7
这个应该读作
- "
z
指定后面的d
... 转换说明符适用于size_t
或相应的有符号整数类型参数 ..."(两种类型)和 "z
指定后面的u
... 转换说明符适用于size_t
或相应的有符号整数类型参数 ...”(两种类型)
或
- "
z
指定后面的d
... 转换说明符适用于相应的有符号整数类型参数 ..."(仅限有符号类型)和"z
指定以下u
... 转换说明符适用于size_t
"(仅限无符号类型)。
我一直在使用 #2 定义,但现在不太确定。
Which is correct, 1, 2, or something else?
If #2 is correct, what is an example of a type that can use
"%zd"
?
根据我所做的小测试,"zd" 始终为真,但 "zu" 不适用于负数。
测试代码:
#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;
}
"%zd"
格式的 printf
需要一个对应于无符号类型 size_t
.
标准 C 不提供此类型的名称或确定它是什么的好方法。例如,如果 size_t
是 unsigned long
的 typedef,那么 "%zd"
需要一个 long
类型的参数,但这不是一个可移植的假设。
标准要求相应的有符号和无符号类型对 non-negative 值使用相同的表示,这两种类型都可以表示。一个脚注说这意味着它们可以作为函数参数互换。所以这个:
size_t s = 42;
printf("s = %zd\n", s);
应该可以,并且应该打印“42”。它会将无符号类型 size_t
的值 42
解释为对应的有符号类型。但确实没有充分的理由这样做,因为 "%zu"
也是正确且定义明确的,无需诉诸其他语言规则。并且 "%zu"
适用于类型 size_t
的 所有 值,包括那些超出相应符号类型范围的值。
最后,POSIX在headers<unistd.h>
and <sys/types.h>
中定义了一个类型ssize_t
。尽管 POSIX 没有明确说明,但 ssize_t
很可能是 size_t
对应的签名类型。
因此,如果您正在编写 POSIX-specific 代码,"%zd"
(可能)是打印 ssize_t
.
更新:POSIX explicitly says ssize_t
不一定是 size_t
的签名版本,所以这是不明智的编写假定它是的代码:
ssize_t
This is intended to be a signed analog of
size_t
. The wording is such that an implementation may either choose to use a longer type or simply to use the signed version of the type that underliessize_t
. All functions that returnssize_t
(read()
andwrite())
describe as "implementation-defined" the result of an input exceeding {SSIZE_MAX
}. It is recognized that some implementations might haveint
s that are smaller thansize_t
. A conforming application would be constrained not to perform I/O in pieces larger than {SSIZE_MAX
}, but a conforming application using extensions would be able to use the full range if the implementation provided an extended range, while still having a single type-compatible interface. The symbolssize_t
andssize_t
are also required in<unistd.h>
to minimize the changes needed for calls toread()
andwrite()
. Implementors are reminded that it must be possible to include both<sys/types.h>
and<unistd.h>
in the same program (in either order) without error.