printf转换说明符的大小限制

6

printf的转换说明符是由标志、宽度、精度、长度修饰符和转换说明符组成的%。是否存在转换说明符大小的实际限制?

例如,%s的长度为2个字符,而%08.2f的长度为6个字符。我的问题是,根据C99标准,可以创建的格式字符串中最大单个规范的长度是多少?


我很好奇 - 除了好奇心之外,你还有其他想知道的原因吗? - nategoose
@nategoose:我正在考虑一个非常特殊的snprintf包装器,并想了解是否可以静态分配一些临时缓冲区。 - zaharpopov
看一下GNU的libc实现怎么样?如果你允许它所做的一切,那应该足够好了。 - Peter G.
我认为一个足够简单易读的实现,我曾经看过的只是按照它所走的方式解释转换规范 - 使用状态机和一些整数变量,直到它到达类型。然后数据类型处理代码使用这些整数和参数输出(当然要处理默认状态),因此除了整数字符串太大而无法适应整数外,没有其他限制。我认为这就是Nut/OS的实现。 - nategoose
3个回答

2

没有最大长度的转换规范。如果您认为找到了这样的规范,我可以提供一个比它多一个字符的规范。

例如,考虑字段宽度和精度。标准规定它们是十进制整数,但不指定它们的范围。因此,您可以编写具有任意大整数作为字段宽度或精度的转换说明符。


这就是为什么在问题中提到了“实际”的原因,毕竟这个宽度是有限的,大值是无效的。即使是64位,也是实际上有限制的。 - zaharpopov
1
虽然 printf 可能不会(也没有必要)强制执行任何限制,但是由于 printf 返回打印的字符数,因此如果您使用非常大的字段宽度/精度,您将获得未指定/未定义(不清楚哪个)的行为。格式说明符可以具有无限长度的更现实的原因是冗余标志,例如 %+++++++++++++++++++++++d - R.. GitHub STOP HELPING ICE
@zaharpopov:嗯,这个问题有两种方法。1)实际的2)根据标准的。我采取了后者的方法。前者取决于编译器和库的实现。 - laalto

1

如果你指的是一个字面字符串,它有4095个字符

5.2.4.1 翻译限制
...
-- 字符串字面值或宽字符串字面值中的4095个字符(在连接后)
...

我曾经被C89的509个字符限制所困扰(不适用于printf/scanf格式字符串),所以这是C99带来的好变化之一 :-)


编辑:glibc实现(非标准定义

glibc实现从read_int函数获取宽度。
因此,对于这个实现,显然,也许,限制是INT_MAX(我还没有搜索read_int函数)。


1
是的,但这不是我的问题所涉及的。格式可能不是字面意思 - 我的问题是关于在“%”之后的最大说明符长度。 - zaharpopov

1
printf的转换规范是%后跟标志、宽度、精度、长度修饰符和转换说明符。是否有转换规范大小的实际限制?
我过去曾处理过几个标准的printf实现,我的一般印象是没有特定的限制。
格式字符串通常逐个字符解析。(想想简单的FSM。)大多数printf实现避免在内部缓冲任何内容,甚至对于数字也使用char by char转换为十进制数(甚至不使用atoi)。
您可以查看例如printf在FreeBSD内核中的实现方式(许多其他实现经常提取代码)。这肯定是一个简化的实现(带有几个内核特定的调整),但它反映了格式字符串通常如何处理。
N.B.刚刚检查了glibc的vfprintf()实现,如果需要,它们会在内部分配一个缓冲区(malloc())。因此,也没有特定的限制。
我的问题是,根据C99标准,可以创建的格式字符串中最大单个规范的长度是多少?
据我所知,格式规范符是字符串的一部分,而字符串长度并没有被标准限制。正如我上面提到的,我也从未见过有任何这样的限制的实现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接