How does C Handle Integer Literals with Leading Zeros, and What About atoi?
Solution 1:
Leading zeros indicate that the number is expressed in octal, or base 8; thus, 010 = 8. Adding additional leading zeros has no effect; just as you would expect in math, x + 0*8^n = x; there's no change to the value by making its representation longer.
One place you often see this is in UNIX file modes; 0755 actually means 7*8^2+5*8+5 = 493; or with umasks such as 0022 = 2*8+2 = 10.
atoi(nptr)
is defined as equivalent to strtol(nptr, (char **) NULL, 10)
, except that it does not detect errors - as such, atoi()
always uses decimal (and thus ignores leading zeros). strtol(nptr, anything, 0)
does the following:
The string may begin with an arbitrary amount of white space (as determined by
isspace(3)
) followed by a single optional'+'
or'-'
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).
So it uses the same rules as the C compiler.
Solution 2:
Be careful!
In this statement 005
is an octal constant.
int a = 005;
In this case it doesn't matter because a single digit octal constant has the same value as the equivalent decimal constant but in C: 015 != 15
Whether an integer literal is expressed in octal, decimal or hexadecimal, once it is parsed by the compiler it is just treated as a value. How an integer is output via printf
depends only on its type, its value and the format specifiers (and the active locale).
Solution 3:
The fact that a leading zero indicates a number is octal is something that's often forgotten. I've seen it cause confusion several times, such as when someone tried to input an IP address using a nice, regular format for the octets:
192.168.010.073
and the parser interpreted the last 2 octets as octal numbers.
The only thing worse than C's unfortunate use of leading zeros to make a number octal is Javascript's handling of leading zeros to sometimes make a number octal (the number is octal if the rest of the digits are OK - less than 8 - decimal otherwise). In Javascript, (017 == 15)
but (018 == 18)
.
I'd rather there be an error; actually I'd rather drop octal literal support altogether. At least use a more in-your-face prefix, like maybe
0t10 (ocTal 8)
0k17 (oKtal 15)
But I'm about 35 years too late with my proposal.
Solution 4:
A number with a leading zero means octal encoding in all versions of C. So 011 == 9 == 0x9
.
Octal is a numbering system based on 8 (instead of 10 for decimal or 16 for hex). So 011 == 1*8 + 1, 013 == 1*8 + 3
, etc.