Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do positional arguments like "1$" work with printf()?

Tags:

c

format

printf

By man I find

               printf("%*d", width, num);

and

               printf("%2$*1$d", width, num);

are equivalent.

But IMO the second style should be the same as:

               printf("%*d", num, width);

However via testing it seems man is right; why?

like image 240
Je Rog Avatar asked Jun 12 '11 14:06

Je Rog


People also ask

What does %s mean in fprintf?

Below are several examples of printing information from variables using fprintf. Notice the use of %s to print a string, and %d to print an integer, and %f to print a number with a decimal (a floating point number).

What is %A in printf?

The %a formatting specifier is new in C99. It prints the floating-point number in hexadecimal form. This is not something you would use to present numbers to users, but it's very handy for under-the-hood/technical use cases. As an example, this code: printf("pi=%a\n", 3.14); prints: pi=0x1.91eb86p+1.

How does printf work?

The printf function (the name comes from “print formatted”) prints a string on the screen using a “format string” that includes the instructions to mix several strings and produce the final string to be printed on the screen.

How to format a string in Java using printf?

To format a simple string, we'll use the %s combination.printf("%2.2s", "Hi there!"); The first x number in %x. ys syntax is the padding. y is the number of chars.


2 Answers

The relevant part of the POSIX specification of printf() defines this behaviour:

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.

The %n$ identifies the argument whose value is to be printed - argument 2 in your example.

The *n$ identifies the argument whose value is to be treated as the format width - argument 1 in your example.

So, those writing the manual followed the standard.


You argue in a comment:

2$* should match the 2nd parameter while 1$d should match the first one, but it turns out that it's not true in the case of printf("%2$*1$d", width, num);.

As noted already, the standard clearly attaches the n$ parts as postfix modifiers of % and *, rather than as prefix modifiers of the format conversion specifier (d in this example) and *. Your putative design could, probably, be made to work, but was not the design chosen.

like image 190
Jonathan Leffler Avatar answered Sep 17 '22 15:09

Jonathan Leffler


In your second example:

printf("%2$*1$d", width, num);

The first number, 2, is attached to the format specifier, and the second number, 1, is attached to the *. If you read the documentation for printf, this is clear. Nothing unusual is happening.

like image 31
R.. GitHub STOP HELPING ICE Avatar answered Sep 19 '22 15:09

R.. GitHub STOP HELPING ICE