为什么 snprintf() 采用 size_t 大小限制,但 returns 打印的字符数为 int?
Why does snprintf() take a size_t size limit, but returns an int number of chars printed?
令人尊敬的 snprintf()
函数...
int snprintf( char *restrict buffer, size_t bufsz, const char *restrict format, ... );
- return它打印的字符数,或者更确切地说,如果没有缓冲区大小限制,它会打印的字符数。
- 取characters/bytes中缓冲区的大小。
缓冲区大小为 size_t
但 return 类型仅为 int
有何意义?
如果 snprintf()
应该能够将多于 INT_MAX
个字符打印到缓冲区中,那么它肯定必须 return 一个 ssize_t
或一个 size_t
(size_t) - 1
表示错误,对吗?
如果它不能打印超过 INT_MAX
个字符,为什么 bufsz
是 size_t
而不是 unsigned
或int
?或者 - 它是否至少被正式限制为不大于 INT_MAX
的值?
printf
早于 size_t
和类似的“便携式”类型的存在——当 printf
首次标准化时,sizeof
的结果是 int
.
这也是为什么 printf
参数列表中读取的参数 *
宽度或格式精度是 int
而不是 [=11= 的原因].
snprintf
较新,因此它作为参数的大小被定义为 size_t
,但 return 值保留为 int
使其与 printf
和 sprintf
.
相同
请注意,您可以使用这些函数打印多于 INT_MAX
个字符,但如果这样做,return 值是未指定的。在大多数平台上,int
和 size_t
都将以相同的方式被 return 编辑(在主 return 值寄存器中),只是 size_t
值可能超出 int
的范围。如此多的平台实际上来自所有这些例程 return a size_t
(或 ssize_t
),并且超出范围的事情通常会正常工作,即使标准不要求它。
If snprintf()
is supposed to be able to print more than INT_MAX
characters into the buffer, surely it must return an ssize_t
or a size_t
with (size_t) - 1
indicating an error, right?
不完全是。
C 对 fprintf()
和朋友也有 环境限制。
The number of characters that can be produced by any single conversion shall be at least 4095." C17dr § 7.21.6.1 15
每个 %
超过 4095 的任何东西都会冒可移植性的风险,因此 int
,即使是 16 位 (INT_MAX = 32767
),也足以满足大多数可移植代码的目的。
注意:ssize_t
不是 C 规范的一部分。
How does it make sense for the buffer size to be size_t
, but for the return type to be only an int?
The official C99 rationale document 没有讨论这些特定的考虑因素,但大概是出于一致性和(单独的)意识形态原因:
所有 printf
家族功能 return 和 int
具有基本相同的意义。这是在发明 size_t
之前就定义的(对于原始的 printf
、fprintf
和 sprintf
)。
type size_t
在某种意义上是传达大小和长度的正确类型,因此它被用于 snprintf
和 vsnprintf
的第二个参数这些是在 C99 中引入的(连同 size_t
本身)。
If snprintf()
is supposed to be able to print more than INT_MAX
characters into the buffer, surely it must return an ssize_t
or a size_t
with (size_t) - 1
indicating an error, right?
那将是一个内部更一致的设计选择,但不是。似乎已经选择了跨函数系列的一致性。请注意,此系列中的 none 函数已记录了它们可以输出的字符数限制,并且它们的一般规范暗示没有内在限制。因此,他们都遇到了输出很长的相同问题。
And if it is not supposed to be able to print more than INT_MAX
characters, why is bufsz a size_t
rather than, say, an unsigned
or an int
? Or - is it at least officially constrained to hold values no larger than INT_MAX
?
除了必须表示为 size_t
的隐式约束外,没有关于第二个参数值的记录约束。甚至在最新版本的标准中也没有。但请注意,也没有任何内容表明 int
类型不能表示 size_t
可表示的所有值(尽管在大多数实现中确实不能)。
所以是的,当通过这些函数输出非常大的数据时,实现将难以根据规范运行,其中“非常大”是依赖于实现的。那么,作为一个实际问题,不应依赖于使用它们在单个调用中发出非常大的输出(除非有人打算忽略 return 值)。
大小和 return 之间的差异已在线程 https://www.austingroupbugs.net/view.php?id=761 的标准组中讨论。这是该线程末尾发布的结论:
Further research has shown that the behavior when the return value would overflow int was clarified by WG14 in C99 by adding it into the list of undefined behaviors in Annex J. It was updated in C11 to the following text:
"J.2 Undefined behavior
The behavior is undefined in the following circumstances:
[skip]
— The number of characters or wide characters transmitted by a formatted output function (or written to an array, or that would have been written to an array) is greater than INT_MAX (7.21.6.1, 7.29.2.1)."
请注意,此说明未提及 snprintf 的大小参数或缓冲区的大小。
令人尊敬的 snprintf()
函数...
int snprintf( char *restrict buffer, size_t bufsz, const char *restrict format, ... );
- return它打印的字符数,或者更确切地说,如果没有缓冲区大小限制,它会打印的字符数。
- 取characters/bytes中缓冲区的大小。
缓冲区大小为 size_t
但 return 类型仅为 int
有何意义?
如果 snprintf()
应该能够将多于 INT_MAX
个字符打印到缓冲区中,那么它肯定必须 return 一个 ssize_t
或一个 size_t
(size_t) - 1
表示错误,对吗?
如果它不能打印超过 INT_MAX
个字符,为什么 bufsz
是 size_t
而不是 unsigned
或int
?或者 - 它是否至少被正式限制为不大于 INT_MAX
的值?
printf
早于 size_t
和类似的“便携式”类型的存在——当 printf
首次标准化时,sizeof
的结果是 int
.
这也是为什么 printf
参数列表中读取的参数 *
宽度或格式精度是 int
而不是 [=11= 的原因].
snprintf
较新,因此它作为参数的大小被定义为 size_t
,但 return 值保留为 int
使其与 printf
和 sprintf
.
请注意,您可以使用这些函数打印多于 INT_MAX
个字符,但如果这样做,return 值是未指定的。在大多数平台上,int
和 size_t
都将以相同的方式被 return 编辑(在主 return 值寄存器中),只是 size_t
值可能超出 int
的范围。如此多的平台实际上来自所有这些例程 return a size_t
(或 ssize_t
),并且超出范围的事情通常会正常工作,即使标准不要求它。
If
snprintf()
is supposed to be able to print more thanINT_MAX
characters into the buffer, surely it must return anssize_t
or asize_t
with(size_t) - 1
indicating an error, right?
不完全是。
C 对 fprintf()
和朋友也有 环境限制。
The number of characters that can be produced by any single conversion shall be at least 4095." C17dr § 7.21.6.1 15
每个 %
超过 4095 的任何东西都会冒可移植性的风险,因此 int
,即使是 16 位 (INT_MAX = 32767
),也足以满足大多数可移植代码的目的。
注意:ssize_t
不是 C 规范的一部分。
How does it make sense for the buffer size to be
size_t
, but for the return type to be only an int?
The official C99 rationale document 没有讨论这些特定的考虑因素,但大概是出于一致性和(单独的)意识形态原因:
所有
printf
家族功能 return 和int
具有基本相同的意义。这是在发明size_t
之前就定义的(对于原始的printf
、fprintf
和sprintf
)。type
size_t
在某种意义上是传达大小和长度的正确类型,因此它被用于snprintf
和vsnprintf
的第二个参数这些是在 C99 中引入的(连同size_t
本身)。
If
snprintf()
is supposed to be able to print more thanINT_MAX
characters into the buffer, surely it must return anssize_t
or asize_t
with(size_t) - 1
indicating an error, right?
那将是一个内部更一致的设计选择,但不是。似乎已经选择了跨函数系列的一致性。请注意,此系列中的 none 函数已记录了它们可以输出的字符数限制,并且它们的一般规范暗示没有内在限制。因此,他们都遇到了输出很长的相同问题。
And if it is not supposed to be able to print more than
INT_MAX
characters, why is bufsz asize_t
rather than, say, anunsigned
or anint
? Or - is it at least officially constrained to hold values no larger thanINT_MAX
?
除了必须表示为 size_t
的隐式约束外,没有关于第二个参数值的记录约束。甚至在最新版本的标准中也没有。但请注意,也没有任何内容表明 int
类型不能表示 size_t
可表示的所有值(尽管在大多数实现中确实不能)。
所以是的,当通过这些函数输出非常大的数据时,实现将难以根据规范运行,其中“非常大”是依赖于实现的。那么,作为一个实际问题,不应依赖于使用它们在单个调用中发出非常大的输出(除非有人打算忽略 return 值)。
大小和 return 之间的差异已在线程 https://www.austingroupbugs.net/view.php?id=761 的标准组中讨论。这是该线程末尾发布的结论:
Further research has shown that the behavior when the return value would overflow int was clarified by WG14 in C99 by adding it into the list of undefined behaviors in Annex J. It was updated in C11 to the following text:
"J.2 Undefined behavior The behavior is undefined in the following circumstances: [skip] — The number of characters or wide characters transmitted by a formatted output function (or written to an array, or that would have been written to an array) is greater than INT_MAX (7.21.6.1, 7.29.2.1)."
请注意,此说明未提及 snprintf 的大小参数或缓冲区的大小。