tags:

views:

679

answers:

7

When you create an integer with leading zeros, how does c handle it? Is it different for different versions of C?

In my case, they just seem to be dropped (but maybe that is what printf does?):

#include <stdio.h>

int main() {
    int a = 005;
    printf("%i\n", a);
    return 0;
}

I know I can use printf to pad with 0s, but I am just wondering how this works.

+1  A: 

Integers don't have "leading zeros" a 5 is a 5, you may write its string representation with leading 0 if you want, for that you have the printf modifiers.

Arkaitz Jimenez
yes, but 010 is not 10.
tvanfosson
I didn't say that it was the same. Obviously his intentions were to add 0s, not using octal.
Arkaitz Jimenez
It wasn't so obvious to me since he indicated that he already knew he could pad with 0's on output. Obviously, integers do have leading 0's when you want to express them in octal notation.
tvanfosson
+23  A: 

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.

bdonlan
Thanks, maybe this a different question, but with atoi or strtol without a base of zero, what happens with leading zeros?
Kyle Brandt
I understand perfectly now, thank you! I'm sure this is in all my basic C books, just didn't stick in my head :-P
Kyle Brandt
+7  A: 

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).

Charles Bailey
but printf uses decimal.
Behrooz
@behrooz: it prints out decimal 5, because decimal and octal 5 are the same value. This isn't true for 010 and 10. Print out the first and you get 8 (the decimal string representation of binary 1000 or octal 010). Print out the second and you get 10 (binary 1010 or octal 012).
tvanfosson
+5  A: 

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.

Aaron Digulla
A: 

In your particular case, the zeroes are being dropped by printf. All leading zeroes are stripped out by the compiler except for the initial zero which causes your compiler to treat the integer as octal. For 005, both the octal and decimal representations are the same and should not bother you but still, it's asking for trouble unless you specifically meant the octal representation.

Leading zeroes have to do purely with the string representation of the integer. To print with leading zeroes, use "%03d". This will ensure a field length of 3.

In general, "%<x>d" will print an integer x characters wide and will pad with leading spaces. "%0<x>d" will do the same thing but will pad with leading zeroes.

Vulcan Eager
-1, the leading zeros are not "dropped by printf". Literals in the source are converted to a binary representation (with no concept ofleading zeros) by the compiler. printf has no idea how the value was represented in the source.
Andrew Medico
Point taken. Corrected.
Vulcan Eager
+2  A: 

You should try:

int a = 5;
printf("%03i\n", a);

0 means "pad with zeroes", 3 is the desired length of output.

Edit: sorry, I've just read that you know how to do it. Nevertheless I'll leave this post for others who might have this problem.

madej
A: 

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.

Michael Burr