2

In "Thinking in C++" Bruce Eckel writes :

"In C, a const always occupies storage and its name is global."

He also adds :

"In C a const always creates storage."

In ANSI C standard (both C89 and C11) I read:

"The implementation may place a const object that is not volatile in a read-only region of storage. Moreover, the implementation need not allocate storage for such an object if its address is never used."

Is "Thinking in C++" inaccurate or do I misunderstand the statement in the standard? Maybe what is stated in the book is only valid for an abstract machine?

mrn
  • 959
  • 5
  • 15
  • 1
    Possible duplicate of [Where are constant variables stored in C?](http://stackoverflow.com/questions/1576489/where-are-constant-variables-stored-in-c) – BadZen Dec 06 '16 at 19:50
  • It appears it is. I don't understand what is the confusing part. Bruce Eckel can be wrong. But note, that "*Thinking in C++*" is not the same as *Thinking in C*", so the C++ standard might have a different specification regarding constants. – Iharob Al Asimi Dec 06 '16 at 19:51
  • 2
    Thinking in C++ is not Thinking in C but this quote talks directly about C language. – mrn Dec 06 '16 at 19:52
  • @BadZen It's not exactly a duplicate, it's more a related question – Stargateur Dec 06 '16 at 19:55
  • 2
    Eckel's quote says something about /C (global) const variables/. The question is if that statement is accurate or not. If compilers may optimize out global const variables (they may), the statement is inaccurate if he's talking about modern C. (I don't know /which/ C Eckel refers to, however...) – BadZen Dec 06 '16 at 19:58
  • 2
    In C, `const int x = 123;` --> `123` is a _constant_. `x` is a `const` object. Title would be better as "Does a `const` in C always occupy storage?" as `const` object are not truly _constant_. Attempting to change a `const` object is UB, not a compile time failure. – chux - Reinstate Monica Dec 06 '16 at 20:07
  • @chux Thanks, title corrected. – mrn Dec 06 '16 at 20:10
  • 2
    A `const` does not always create storage. A non-volatile integral constant whose address is never taken will almost always be eliminated by compiler optimization and this behavior is permitted by the standard. Without context, I don't know what the book is talking about – Yan Zhou Dec 06 '16 at 20:39
  • 2
    The C standard is correct. The book appears to be incorrect — there might be mitigating circumstances from the context surrounding the quote, but in the absence of such, the quote is wrong. It is wrong in detail. One difference between C and C++ is that in C++, constants defined at file scope outside any namespace are not global, even if there is no `static` in the definition; they are not visible as linkable symbols outside the source file. In C, such constants are defined as global and are visible outside the source file. – Jonathan Leffler Dec 06 '16 at 20:47

3 Answers3

2

In C, a const always occupies storage and its name is global.

This is nonsense, though I'd like to see more of the context.

First off, const is a a type qualifier, not a kind of entity. It means "read-only", not "constant" (something is "constant" if it can be evaluated at compile time). Referring to something as "a const" is like calling it "a read-only".

The author probably means something like "an object of some const-qualified type".

For example, given

const int n = 42;

you might say that n is "a const".

In the abstract machine, any object, const or not, occupies storage. It has an address, and that address is unchanged throughout the object's lifetime. You can evaluate &n and it will yield a pointer value of type const int*.

However, a compiler is free to omit the storage for any object if that storage is not actually used. Though n is not a constant expression in C, it's perfectly legal for a compiler to replace each occurrence of n in an expression by the constant value 42. If it can prove that no use of n depends on it being stored somewhere, it can optimize away the storage that would otherwise have been used to hold it.

As for its name being "global", that's also nonsense. The C standard doesn't use the term "global". An identifier has a scope, which defines the region of program text in which the name is visible. If n is defined inside a function, the name is visible only within the enclosing block. If it's defined outside any function, the name has file scope, and its name is visible from its definition to the end of the source file.

The const type qualifier doesn't affect either the lifetime of the object or the scope of its name.

The author is probably trying to show a difference between C and C++. There is such a difference, but it's not what the author says it is. In C, given

const int n = 42;

the name n, when used in an expression, is not a constant expression. That means, for example, it can't be used in a case label. (This applies only if the initial value is itself a constant expression.) In C++, the name n is a constant expression. However, C++ still permits you to take the address of n.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
1

First, it's been a long time (and many languages ago) since I wrote that so I'm relying on memory here.

It seems unlikely that a const only visible within a file would always need to allocate storage, so I suspect I was referring to a global const defined in one file and readable in other files. In that case there would have to be an address for the linker, and no compile-time optimizer could recognize if that address was never used (I'm not sure here about the capabilities of linkers; whether a linker could detect the lack of reference to that storage and change the code so it doesn't allocate it. Maybe, but it seems a stretch). And if it's global it does seem like it could be in a library where it could be referenced by some as-yet unwritten piece of code, and that would argue for required storage.

Ultimately, however, rely on the standard and not my writing or reasoning. Before drawing a final conclusion I would recommend seeing what the C++ standard says about this (and I only worked on the original one so I'm sure it's changed) vs what the C standard says. C++ might have additional constraints that aren't in the C standard.

Hope that helps.

-- Bruce

user1677663
  • 1,431
  • 15
  • 21
1

While it is true that const-qualified objects in C do not qualify as constants (i.e. compile-time constants), the language specification still states that

6.7.3 Type qualifiers

4 The properties associated with qualified types are meaningful only for expressions that are lvalues.132)

and then additionally clarifies it with

132) The implementation may place a const object that is not volatile in a read-only region of storage. Moreover, the implementation need not allocate storage for such an object if its address is never used.

This means that const-qualified objects do not necessarily occupy storage.

So, conceptually const-qualified objects in C require definition and thus occupy storage, but it can be optimized away by the compiler as part of standard-permitted optimization.

Note though, that external const-qualified objects in C maintain external linkage (unless overridden by an explicit static specifier), which means that storage elimination for such objects would require a global effort (must be done at linking stage).

Community
  • 1
  • 1
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765