First, let me show you the results of your code in 5.8.0 with warnings enabled:
The relevant part of the perldocs follows:3.1416 Invalid conversion in printf: "%f" at - line 3. %4.4lf Invalid conversion in printf: "%f" at - line 4. %4.4hf Invalid conversion in printf: "%q" at - line 5. %4.4qf 3.1416 3.1416
For floating point conversions, numbers are usually assumed to be the default floating point size on your platform (double or long double), but you can force 'long double' with q, L, or ll if your platform supports them.l interpret integer as C type "long" or "unsigned long" h interpret integer as C type "short" or "unsigned short" q, L or ll interpret integer as C type "long long" or "unsigned lo +ng long" (if your platform supports such a type, else it is an e +rror)
Now, even according to this, the l and h formats only apply to integers and never floats. So, Perl just warns you and then does what it prints what it can make sense of (the literal string). According to these docs, however, q should not be producing an error.
Next source is the best ANSI C description I could find:
The optional character l (ell) specifying that a following d, i, o, u, x, or X conversion applies to a pointer to a long int or unsigned long int argument, or that a following n conversion corresponds to a pointer to a long int argument.
The character L specifying that a following e, E, f, g, or G conversion corresponds to a long double argument.
The optional character h, specifying that a following d, i, o, u, x, or X conversion corresponds to a short int or unsigned short int argument, or that a following n conversion corresponds to a pointer to a short int argument.
Source: http://www.introl.com/introl-demo/Libraries/C/ANSI_C/stdio/fprintf.html
Again, h and l only are for integers, and in this case q and ll don't even exist. These are also the flags that Visual C++ understands, in addition to I64. Of course, Perl is much more than ANSI C, as the previous docs indicated.
So, let's go to the likely inspiration for Perl's s/printf, the GNU C library:
Source: http://www.cgi101.com/class/ch16/envman.cgi?sprintfh A following integer conversion corresponds to a short int or unsigned short int argument, or a fol lowing n conversion corresponds to a pointer to a short int argument. l (ell) A following integer conversion corresponds to a long int or unsigned long int argument, or a fol lowing n conversion corresponds to a pointer to a long int argument, or a following c conversion cor responds to a wint_t argument, or a following s conversion corresponds to a pointer to wchar_t argument. ll (ell-ell). A following integer conversion corre sponds to a long long int or unsigned long long int argument, or a following n conversion corresponds to a pointer to a long long int argument. L A following a, A, e, E, f, F, g, or G conversion corresponds to a long double argument. (C99 allows %LF, but SUSv2 does not.) q (`quad'. BSD 4.4 and Linux libc5 only. Don't use.) This is a synonym for ll.
For one thing, it looks like ll is also an integer only conversion, but Perl lets it slide as a synonym for L. However, q, which is a synonym for ll, doesn't even work on integers. The manpage says we shouldn't use it, it looks like Perl has decided we shouldn't use it, but no one has updated the perldocs to show this.
Two comments: One can argue how Perl should handle incorrect parameters, but I think the current warning is probably sufficient. Also, I'm not quite sure why ll decided to start working on non-ints in 5.8.0, but I still believe it's either the docs being a bit behind or ahead of the times.
Note: in Win32, the tests you performed behave exactly the same, if you're curious.
In reply to Re: printf size flag incompatibility
by Ionitor
in thread printf size flag incompatibility
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |