5

I am reading modern C, and on page 66, I come across following section:

Remember that value 0 is important. It is so important that it has a lot of equivalent spellings: 0, 0x0, and ’\0’ are all the same value, a 0 of type signed int. Zero has no decimal integer spelling: 0.0 is a decimal spelling for the value 0 but is seen as a floating-point value with type double.

I am a little confused, why "Zero has no decimal integer spelling"? Isn't 0 decimal integer spelling?

5
  • 4
    0 and 1 are not specifically decimal values. They have the same value in any number base. Commented Jul 23 at 8:23
  • 2
    This is yet another misuse of the word 'decimal' to mean 'fractional digit', or 'having a fractional part'. It doesn't mean that. It is a radix. Note that the Java Language Specification does not perpetrate this illiteracy. Indeed it has a grammar production IntegerLiteral : DecimalIntegerLiteral, and it says 'An integer literal may be expressed in decimal' (Java Language Specification #3.10.1 Integer Literals). So the author of your book is quite incorrect. Commented Jul 23 at 8:39
  • @JensGustedt, the author of Modern C, hangs out around here sometimes. Since the answers to this question have different takes on what he meant, perhaps he can be enticed to chime in. Commented Jul 23 at 14:28
  • It's just a "humorful" way of saying that decimal zero (0.0) produces a double and not an integer like the other zeroes. The answers are reading waaay too much into this. Commented Jul 23 at 16:31
  • I think the whole point of it is to point out that integer constants that start with 0 like 0123 are explicitly octal and it's a common beginner mistake to write them like that, thinking they just added some zero padding for formatting purposes. Commented Aug 14 at 7:03

5 Answers 5

10

The author is probably trying to be friendly with beginners and uses a humoristic tone... Yet there is actually no such thing as a decimal integer or an octal integer. There are ways to specify integer constants in different bases: base 10 (decimal) as for 42, base 16 (hexadecimal) as for 0x2a, base 8 (octal) as 052 and, since C23, base 2 (binary) eg: 0b101010. Decimal or octal apply for the representation of the integer value, they are not an attribute of the integer itself.

According to the C syntax rules, 0 is an octal constant because it matches the lexical grammar for octal-constant:

octal-constant:
0
octal-constant opt octal-digit

Whereas decimal constants match this rule:

decimal-constant:
nonzero-digit
decimal-constant opt digit

Since its value is zero anyway, it does not matter if it is considered an octal literal or a decimal literal and the distinction underscored in the book is purely academic and somewhat confusing for beginners and even non-beginners.

Sign up to request clarification or add additional context in comments.

8 Comments

It's also a bit moronic, because such language is not useful to the beginner. Grammar production rules may make 0 an octal literal,cbut that is meaningless in any context outside the parser. Makes me wonder what ither nonsense the author inflicts upon the reader
I guess that's debatable. The particular observation in question makes little difference to a beginner or to anyone else, but it draws attention to the fact that the data types of constants are determined mainly by the form of their representations in source code. Beginners very much need to appreciate that, and to learn and understand the details.
OP has very plainly demonstrated that it does make a difference to a beginner just by asking the question itself. In this case the information is overload noise. Radix is not a data type. Rather than confuse the user with such language, why not have a section that simply explains how the syntax of literals matters in expressing things like radix and data type?
Why not indeed, @Dúthomhas? And lo, the quoted text appears towards the end of a section that provides just such a discussion of the syntax of integer constants. We should also qualify the term "beginner" here. The book is not aimed at beginners to programming. It explicitly says "If you have never programmed before, this book will be tough." It is aimed mainly at programmers already familiar with programming in one or more languages (possibly including C). I would have no qualms about expecting that audience to have the needed conceptual framework.
Excellent. Thank you!
I agree. The book does a great job explaining details which are difficult to read directly from the standard and I have much respect for Jens Gustedt, but I still think the particular sentence "Zero has no decimal integer spelling" is unhelpful. Beginner or not, the sentence has to be read into the very specific context of the C grammar and it has no consequence on the language semantics which probably is the concern of the vast majority of readers. It could be explained much less subtly, e.g. "Since 0 is an octal constant there is no decimal integer constant with the value of 0".
@Dúthomhas: yes, I agree and amended my answer with a grain of salt. The author is a member here, you might want to share your views with him directly: stackoverflow.com/users/366377/jens-gustedt
I am unfortunately a little outspoken about some pedagogy issues, and my people skills could certainly use some work. I suspect in the grand scheme of things it does not matter much, just as John Bollinger said. (BTW, I was the first to upvote your answer.) 😉
5

The author takes a quirk of no consequence in the C grammar and elevates it excessively.

The distinction between decimal constants and other constants the author discusses exists only in parsing the grammar of the C language. In regard to 0, it has no effect on actual language semantics.

In C 2024 6.4.5.2, the C grammar classifies an integer-constant as a decimal-constant, an octal-constant, a hexadecimal-constant, or a binary-constant (which is new). They may also have an integer-suffix, like l or u, not discussed here. 123 is a decimal constant, 0123 is an octal constant, 0x123 is a hexadecimal constant, and 0b101 is a binary constant.

These constants are classified by their initial characters. 0x or 0X indicates a hexadecimal constant, 0b or 0B indicates a binary constant, 0 without b, B, x, or X indicates an octal constant, and the lack of any of these indicates a decimal constant. Because of this, the constant 0 is parsed as an octal constant. The result is an int with value zero. However, supposed we changed the grammar to make 0 a special case, that it were parsed as a decimal constant. The result would be an int of value zero. There would be no observable difference in how any C program were interpreted or executed.

The distinction exists solely as a description of the C grammar and has no effect on C semantics.

The quirk exists merely because it is easier to say “If an integer constant starts with 0, it is octal (or hexadecimal or binary)” than to say “If an integer constant starts with 0, it is octal (or hexadecimal or binary) except if it is just 0, then it is decimal.”

I will note that the distinction between octal and decimal can have a real effect on other values. The type of an integer constant is affected by whether an integer-constant is decimal or other, but only if its value is large. C 2024 Table 2.4 lists the types that are used. If an unsuffixed decimal constant is too large for an int, the next type considered for it is long int, whereas, for an unsuffixed octal constant, the next type is unsigned int. However, for 0, the value always fits, so this difference is inapplicable for it.

Floating-point constants have a similar classification; a floating-constant in the grammar is either a decimal-floating-constant or a hexadecimal-floating-constant (which begins with 0x or 0X). Again, this distinction exists solely in the grammar and has no effect beyond it. Both 0. and 0x0p0 yield a double with value zero.

1 Comment

This should be the most upvoted answer IMO. The (strange) distinction in the type of integer constants depending on not only their value but also whether or not they are specified in decimal representation is the most interesting aspect of this topic.
5

0 is an integer constant. According to the C23 Standard (6.4.4.2 Integer constants) there are classified the following integer constants:

1 integer-constant:

decimal-constant integer-suffixopt 
octal-constant integer-suffixopt 
hexadecimal-constant integer-suffixopt 
binary-constant integer-suffixopt

Decimal constants start with a non-zero digit:

decimal-constant:

nonzero-digit 
decimal-constant ’opt digit

Octal constants start with zero:

octal-constant:

0 
octal-constant ’opt octal-digit

So the integer constant 0 is represented as an integer octal constant. It seems the author of the book means this difference between integer (or character) constant representations. In any case the integer octal constant 0 has type int and the value zero. You can charge the type of the constant by adding a suffix as for example 0ull in which case the octal integer constant will have type unsigned long long int. 0 can be represented as an integer constant in the form for example as character constant '\0' or '\x0' or as a hexadecimal integer constant 0x0 and so on. However 0 has no decimal integer constant representation because all integer constants that start with zero (optionally followed by other digits) are octal integer constants by the definition. That is the rule that octal integer constants start with zero makes the integer constant 0 octal integer constant.

Comments

2

Decimal is not a primitive type in C, like int or double are. Rather the author uses the term decimal integer to mean an integer with a fractional component. If you want to speak the language of mathematics, you would find a contradiction because the class of integers is a subset of rational numbers (decimals).

I will quote from the same page in the book:

The effective value of a decimal floating-point literal may be different from its literal value.

which is to say that floating point numbers are NOT decimals! There are approximations of true fixed precision decimals.

You are correct that 0 is technically an element of both decimals and integers but I believe the author is alluding to the point that floating point numbers are approximate decimals here.

4 Comments

Not all floating point number representations are approximate. For double, about 2^64 representations are exact. It is all the rest that are have an approximate value.
There is a confusion in English (or possibly only in American English) between decimal numbers and decimal fractions. Sometimes "decimal" means "not integer", which is an unfortunate confusion. I think this is what's happening in this answer, but not in the book.
Re “Rather the author uses the term decimal integer to mean an integer with a fractional component”: No, the author uses “decimal integer” to refer to integers represented using the decimal notation system, a positional system in which the value of each digit depends on its position in the numeral. It is decimal because each digit’s position value is ten times the value of the position to its right. As a decimal numeral “123” means one hundred and twenty-three. This is different from what “123” means as an octal numeral, which would be eighty-three.
Re “I believe the author is alluding to the point that floating point numbers are approximate decimals here”: No, they are referring to the classification of the constants in the C grammar.
1

"Spelling" is a strange term to use in this context; "source code representation" is a better if less succinct term perhaps, or just "representation" in context. But specifically regarding the part:

Zero has no decimal integer spelling

the point is that in C an integer literal prefixed with a zero is an octal value, not a decimal value. It is kind of a pedantic point that need not be highlighted perhaps, but it is mentioned a few pages earlier in the text:

enter image description here

2 Comments

Since this question is about pedantry beyond reason, it is ironic that the quoted specification of an octal literal does not really include 0 itself ("the first being 0 and the following between 0 and 7": in the case of 0, the first is 0, but the following is not present and thus not between 0 and 7).
Aside: The "rarely used" octal literals do come in useful sometimes, especially for specifying Unix file mode bits, where "everyone" knows that 0666 is the same value as S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.