printf bad ?

Henry Spencer henry-lqW1N6Cllo0sV2N9l4h3zg at public.gmane.org
Fri Mar 18 20:50:45 UTC 2005


On Fri, 18 Mar 2005, Peter wrote:
> printf "%05d" 08
> it says 'invalid number' for any number of 0's before the 8. Why does it 
> think it's octal ?!

Because the syntax of the arguments (after the format string) to the
printf command is defined -- in the POSIX standard -- to be the same as
that of C constants, with some minor extensions, and in C, a leading 0
means an octal number.  (The fact that the FSF's documentation for the
printf command fails to discuss this is a documentation bug.)

> printf "%05d" 10#08
> -bash: printf: 10#08: invalid number
> 
> (according to the bash manual that notation should force decimal - it 
> does not - not in quotes and not in ticks and not with a 
> backslash-escaped '#').

That notation is for the $(( )) construct, the shell's built-in expression
evaluation; it doesn't apply everywhere.  If you try this:

	printf "%05d" $((10#08))

you'll find that it works.

> I wrote a small C program to test atoi, strtod and strtoul and the 
> latter is broken (is it ?). E.g.:
> plp at plp:~/tc$ ./1 08
> atoi: 8
> strtod: 8.000000
> strtoul: 0

Does your program check to see whether strtoul() actually consumed the
whole string?  If you specified 0 as the "base" argument of strtoul(),
then it follows the C rules, so a leading 0x means hex, a leading 0
followed by a valid octal digit is octal, and otherwise the 0 is the
whole number and there's some trash following it.

atoi() doesn't show this behavior because its input is always decimal by
definition.  strtod() doesn't because there is no octal floating-point
format, so it's taking 08 as decimal.

> I take this to mean that strtoul() assumes the lowest conversion base it 
> can use if the third argument is 0.

No.  Quoth "man strtoul" (after a discussion of possible leading white
space and sign): 

       If base  is  zero  or  16,  the
       string may then include a `0x' prefix, and the number will
       be read in base 16; otherwise, a zero base is taken as  10
       (decimal)  unless the next character is `0', in which case
       it is taken as 8 (octal).

In other words, with a zero base, a leading 0 not followed by x means
octal, period. 

> It should look at the 
> whole string and match the highest base it can, starting from the last 
> character that is not convertible with any base, imho.

That is an interesting notion, but it is *not* the specification for
strtoul().  You don't have to guess how these things work; it's
documented. 

                                                          Henry Spencer
                                                       henry-lqW1N6Cllo0sV2N9l4h3zg at public.gmane.org

--
The Toronto Linux Users Group.      Meetings: http://tlug.ss.org
TLUG requests: Linux topics, No HTML, wrap text below 80 columns
How to UNSUBSCRIBE: http://tlug.ss.org/subscribe.shtml





More information about the Legacy mailing list