fprintf()
family of functions have 5 flag characters '-'
, '+'
, ' '
, '#'
, '0'
.
What is the specified behavior, if any, when a flag is repeated?
#include <stdio.h>
int main(void) {
printf("% d\n", 12); // 12
printf("%00d\n", 34); // 34
printf("%++d\n", 56); // +56
printf("%00*d\n", 5, 78); // 00078
return 0;
}
With my gcc "i686-pc-cygwin/4.9.2" I receive "warning: repeated ' ' flag in format [-Wformat=]", so I assume this is a correct behavior--> warn user and allow repeated flag.
I have yet to find a C99/C11 specification guidance for this corner issue found while trying to write a format parser.
If repeating allowed, the following code is OK. If repeating is not allowed, the 2nd 0
is the width. Then the specifier has 2 widths 0
and *
, which is another problem.
// -------v
printf("%00*d\n", 5, 78); // 00078
The printf() conversion flags are enabled by specifying one or more of the following characters, which may appear in any order: ' The integer portion of the result of a decimal conversion (%i, %d, %u, %f, %g, or %G) is formatted with thousands grouping characters using the non-monetary grouping character.
The Printf module API details the type conversion flags, among them: %B: convert a boolean argument to the string true or false %b: convert a boolean argument (deprecated; do not use in new programs).
In my opinion, the standard is unclear on this point.
The authors of gcc were clearly of the opinion that repeated flags are invalid, since gcc issues a warning by default for something like:
printf("%++d\n", 42);
but that doesn't necessarily tell us what the authors of the standard intended.
The standard permits:
Zero or more flags (in any order) that modify the meaning of the conversion specification.
The flags are -
, +
, space, #
, and 0
. The phrase "Zero or more flags* is, I think, specifically intended to permit different flags to be combined. For example, this:
#include <stdio.h>
int main(void) {
printf("|%6x|\n", 0x123);
printf("|%-6x|\n", 0x123);
printf("|%#6x|\n", 0x123);
printf("|%-#6x|\n", 0x123);
printf("|%#-6x|\n", 0x123);
}
is valid and produces this output:
| 123|
|123 |
| 0x123|
|0x123 |
|0x123 |
In other contexts, the standard is explicit about whether a construct may or may not be repeated. For example, long long int
is distinct from long int
, and long int int
is a syntax error. On the other hand, the standard explicitly says (N1570 6.7.3p5) that:
If the same qualifier appears more than once in the same specifier-qualifier-list, either directly or via one or more
typedefs
, the behavior is the same as if it appeared only once.
The lack of any such statement here makes me suspect that the authors of the standard didn't consider the case of repeating the same flag.
If I'm incorrect about this, and the committee did intend a repeated flag to be equivalent to a single flag, then your format parser should treat them as equivalent. If I'm correct, then the behavior of repeating the same flag is undefined, and your implementation can do anything you like -- including treating them as equivalent to a single flag.
In either case, you're free to issue a warning if you like. Even if the standard defines the behavior of a repeated flag, it's still arguably poor style and worth warning about.
In the C standard (7.21.6.1 The fprintf function) there is written only that
4 Each conversion specification is introduced by the character %. After the %, the following appear in sequence:
— Zero or more flags (in any order) that modify the meaning of the conversion specification.
So I suppose that flags may be repeated. Otherwise there would be some restrictions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With