Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C printf difference between 0 flag & width attribute and precision flag

Tags:

c

printf

libc

I'm currently learning the printf function of libc and I don't understand, what is the difference between:

printf("Test : %010d", 10);

using the 0 flag and 10 as width specifier

and

printf("Test : %.10d", 10);

using 10 as precision specifier

That produce the same output: Test : 0000000010

like image 734
Sadek Avatar asked Nov 12 '16 01:11

Sadek


2 Answers

We'll start with the docs for printf() and I'll highlight their relevant bits.

First 0 padding.

`0' (zero)

Zero padding. For all conversions except n, the converted value is padded on the left with zeros rather than blanks. If a precision is given with a numeric conversion (d, i, o, u, i, x, and X), the 0 flag is ignored.

And then precision.

An optional precision, in the form of a period . followed by an optional digit string. If the digit string is omitted, the precision is taken as zero. This gives the minimum number of digits to appear for d, i, o, u, x, and X conversions, the number of digits to appear after the decimal-point for a, A, e, E, f, and F conversions, the maximum number of significant digits for g and G conversions, or the maximum number of characters to be printed from a string for s conversions.

%010d says to zero-pad to a minimum width of 10 digits. No problem there.

%.10d", because you're using %d, says the minimum number of digits to appear is 10. So the same thing as zero padding. %.10f would behave more like you expected.

I would recommend you use %010d to zero pad. The %.10d form is a surprising feature that might confuse readers. I didn't know about it and I'm surprised it isn't simply ignored.

like image 62
Schwern Avatar answered Sep 28 '22 19:09

Schwern


Both formats produce the same output for positive numbers, but the output differs for negative numbers greater than -1000000000:

printf("Test : %010d", -10); produces -000000010

whereas

printf("Test : %.10d", -10); produces -0000000010

Format %010d pads the output with leading zeroes upto a width of 10 characters.

Format %.10d pads the converted number with leading zeroes upto 10 digits.

The second form is useful if you want to produce no output for value 0 but otherwise produce the normal conversion like %d:

printf("%.0d", 0);  // no output
printf("%.0d", 10);  // outputs 10

Also note that the initial 0 in the first form is a flag: it can be combined with other flags in any order as in %0+10d which produces +000000010 and it can be used with an indirect width as in printf("%0*d", 10, 10); which produces 0000000010.

like image 34
chqrlie Avatar answered Sep 28 '22 18:09

chqrlie