Search code examples
cprintfposix

Passing too few arguments to printf for the format specifier — is it undefined behavior?


As I know, having too few format specifiers for the arguments is considered as undefined behavior (and having too few arguments for the format specifiers is also undefined behaviour). Does this apply to:

printf("%1$d %1$d", 5);

PS Use of "%1$d" as format specifier is an extension to the printf family of functions added by POSIX.


Solution

  • The n$ notation is not part of standard C, but is part of POSIX. The POSIX specification for printf() supports the n$ notation to refer to arguments.

    Conversions can be applied to the nth argument after the format in the argument list, rather than to the next unused argument. In this case, the conversion specifier character % (see below) is replaced by the sequence "%n$", where n is a decimal integer in the range [1,{NL_ARGMAX}], giving the position of the argument in the argument list. This feature provides for the definition of format strings that select arguments in an order appropriate to specific languages (see the EXAMPLES section).

    The format can contain either numbered argument conversion specifications (that is, "%n$" and "*m$"), or unnumbered argument conversion specifications (that is, % and *), but not both. The only exception to this is that %% can be mixed with the "%n$" form. The results of mixing numbered and unnumbered argument specifications in a format string are undefined. When numbered argument specifications are used, specifying the Nth argument requires that all the leading arguments, from the first to the (N-1)th, are specified in the format string.

    In format strings containing the "%n$" form of conversion specification, numbered arguments in the argument list can be referenced from the format string as many times as required.

    It requires that you provide an argument for each n$, and that the format string refers to every argument 1..n. It doesn't say you have to use a different n$ each time.

    The code shown is fine on POSIX systems. Since it uses a POSIX-only feature, it won't be portable to non-POSIX systems that don't have the necessary support as an extension.