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.