Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Using the following code produces different results in 5.6.1 and 5.8.0 (compiled with the same compiler version and the same flags except that 5.8.0 was compiled with ithreads):
# file: printf.pl printf "%4.4f\n", 3.14159; printf "%4.4lf\n", 3.14159; printf "%4.4hf\n", 3.14159; printf "%4.4qf\n", 3.14159; printf "%4.4Lf\n", 3.14159; printf "%4.4llf\n", 3.14159;

Results:

$ /usr/bin/perl5.6.1 printf.pl 3.1416 3.1416 3.1416 %4.4qf %4.4Lf %4.4llf $ /usr/local/bin/perl5.8.0 printf.pl 3.1416 %4.4lf %4.4hf %4.4qf 3.1416 3.1416

As it turns out, none of these printf size flags are tested in either 5.6.1 or 5.8.0 core tests. The relevant config details for each version are the same (snipped for brevity):

Summary of my perl5 (revision 5.0 version 6 subversion 1) configuratio +n: use64bitint=undef use64bitall=undef uselongdouble=undef intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1 +2 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', + lseeksize=8 alignbytes=4, usemymalloc=n, prototype=define Summary of my perl5 (revision 5.0 version 8 subversion 0) configuratio +n: use64bitint=undef use64bitall=undef uselongdouble=undef intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1 +2 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', + lseeksize=8 alignbytes=4, prototype=define

This was noticed when installing Text::Reform with 5.8.0, the module has a single case of using sprintf with an 'lf' (at line 141) which passes all tests on my 5.6.1 but fails on my 5.8.0. My questions: is it at all wise to use these size flags? Is this a perl bug not detected because it isn't tested for? Shouldn't the size flags (l,h,q,L,and ll) simply be ignored if unsupported on a given platform? (platform is linux)

Replies are listed 'Best First'.
Re: printf size flag incompatibility
by Ionitor (Scribe) on Jul 21, 2002 at 23:02 UTC
    Summary: you're using h and l incorrectly, as they are meant to edit integers. The fact that they worked in 5.6.1 probably was a mistake in the first place, and the fix didn't show up in perldelta. Support for q was probably eliminated a while back and no one remembered to update the docs (though it could also be that the docs represent some changes that were never made).
      Summary: you're using h and l incorrectly

      Thanks for the info. But to be clear, I was exploring l, h, etc. exploratively and unfortunately only showed a floating point example. The exact same differences (between 5.6.1 and 5.8.0) show up when used for integer conversions.

      # file: printf.pl printf "%4.4f\n", 1; printf "%4.4lf\n", 1; printf "%4.4hf\n", 1; printf "%4.4qf\n", 1; printf "%4.4Lf\n", 1; printf "%4.4llf\n", 1; #outputs: $ /usr/bin/perl printf.pl 1.0000 1.0000 1.0000 %4.4qf %4.4Lf %4.4llf $ /usr/local/bin/perl printf.pl 1.0000 %4.4lf %4.4hf %4.4qf 1.0000 1.0000

      Where /usr/bin/perl is 5.6.1 and /usr/local/bin/perl is 5.8.0 with the same compile flags (other than ithreads as previously mentioned) and the same version of gcc under linux. It was an integer conversion usage in Damian's Text::Reformat module that brought this to light. Something funny is definitely going on.

        printf doesn't really care whether the arguments are integers or not, it cares about what the size flags immediately precede. If you use the following code:
        use warnings; printf "%4.4i\n", 1; printf "%4.4li\n", 1; printf "%4.4hi\n", 1; printf "%4.4qi\n", 1; printf "%4.4Li\n", 1; printf "%4.4lli\n", 1;
        You then almost get the results that are predicted in the perldocs:
        0001 0001 0001 Invalid conversion in printf: "%q" at - line 5. %4.4qi 0001 0001
        (the zeroes are there because 4.4 ensures that the number will be 4 digits long in the case of an int)

        Of course, there's still that rogue q that doesn't work in 5.6.1 or 5.8.0. However, since q should be the same as L and ll, it's not like Perl is lacking some feature--they just lie about q being a valid alias.

        Again: l and h should only be used when followed by i, never by f. Perl, C, and GNU all appear to agree on this.