Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Re: Const declaration in header files

Reply
Thread Tools

Re: Const declaration in header files

 
 
James Kanze
Guest
Posts: n/a
 
      05-25-2008
On May 24, 10:46 pm, Paavo Helde <(E-Mail Removed)> wrote:
> "Stephen Howe" <sjhoweATdialDOTpipexDOTcom> kirjutas:
> > Just going over some grey areas in my knowledge in C++:


> > 1) If I have


> > const int SomeConst = 1;


> > in a header file, it is global, and it is included in
> > multiple translations units, but it is unused, I know that
> > it does not take up storage in the final executable.


> If something is unused, the compiler can throw it out on
> "as-if" basis, or then not. This is mostly QOI issue. If the
> variable definitions are incorrect and the standard requires a
> diagnostic about that, the implementation has to produce the
> diagnostic regardless of whether he would encode the variables
> in the executable or not.


> If the code happens to take the address of i somewhere, the
> compiler is obliged to ensure that at runtime there will be an
> int variable present with the proper value, so that the
> address can be taken. This most probably means that the value
> is somehow encoded in the executable - I guess this is what
> you mean when you talk about storage in the executable.


The as-if rule holds here as well. Probably the most frequence
case of "taking the address" of an int const is when passing it
to an int const& argument; such arguments generally only result
from the expansion of a template, and in the absense of export,
the compiler has access to the source code of the function, and
can (potentially, at least) see if in fact, it could use the
value directly just as well. Thus, if you have an
std::vector<int>, and do a push_back( SomeConst ) on it, there's
a very good chance that the compiler will not need to allocate
memory for SomeConst then either, despite the fact that in the
abstract machine, it has "taken the address" of the constant.

> However, this is all not so important, unless you work on
> embedded systems, counting single bytes. What is important
> that in C++ the const object definitions can legally appear in
> multiple translation units, without causing linker errors
> about multiple definitions. Of course, all definitions must be
> identical. This enables to use such definitions in common
> header files instead of ancient C macros.


It can be important for two reasons. The first, of course, is
if you have header files with lots of such values, say a couple
hundred, and you end up incorporating the header in many very
small source files. In such cases, while not likely, it *can*
end up making a difference. Particularly if those source files
also have some static variables, which becaue of the extra
variables end up on separate pages in virtual memory. Program
size is important today, for reasons of locality. (The number
of programs affected will be very small, of course.)

The second is that using the variable in a template may cause
problems. The template definition will also be included in
multiple translation units, and according to the standard, there
will be undefined behavior if the token sequence of the
definition differs, OR if any name binding differs. In this
case, the name binding of SomeConst will be different in each
translation unit, i.e. the symbol SomeConst will refer to a
different entity in each translation unit. The standard does
make an exception to this if the symbol is an integral constant
expression (as it is here), with the same type and initializer
value everywhere, *and* only if the address of the object is not
used. (Note that passing the value by reference is using the
address!)

[...]
> > do they wind up in the final executable?


> Why do you care?


Locality? Limited memory? (I've worked on systems where the
entire application had to fit into 64KB, including the OS.)

> > 2) What about the last two statements with const missing and placed
> > in a header file


> > char SomeConst5[] = "A value 3";
> > char *SomeConst6 = "A value 4";


> The const you dropped is not the top-level one, so it does not
> have any significance here.


In the second line. In the first, it changes the linkage.

> > At this point, including in 2+ translation units would fall foul of
> > the one definition rule, right?


> The same as for SomeConst3 (ok) and SomeConst4 (fails).


Do you mean that SomeConst3 and SomeConst5 are the same? I
don't think so.

Actually, the more I think about it, the less sure I am. In C,
at least, there is no such thing as a const array, so the const
isn't top level. G++ treats them as if the arrays themselves
were const, however (i.e. as if the const were top level).

> > 3) If I have


> > const int SomeConst = 1;


> > in a header file, it is global, is it static or extern by default?


> This is not the right termonology, the standard speaks about
> external and internal linkage, etc. I am not sure I can get
> the details right so I skip that.


In this case, supposing that the definition is at namespace
scope, it is internal linkage. But the rules aren't really very
orthogonal, and can easily lead to confusion.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
 
 
 
James Kanze
Guest
Posts: n/a
 
      05-26-2008
On May 25, 10:39 pm, Paavo Helde <(E-Mail Removed)> wrote:
> James Kanze <(E-Mail Removed)> kirjutas:


> > On May 24, 10:46 pm, Paavo Helde <(E-Mail Removed)> wrote:
> >> "Stephen Howe" <sjhoweATdialDOTpipexDOTcom> kirjutas:
> >> > 2) What about the last two statements with const missing and placed
> >> > in a header file


> >> > char SomeConst5[] = "A value 3";
> >> > char *SomeConst6 = "A value 4";


> >> The const you dropped is not the top-level one, so it does
> >> not have any significance here.


> > In the second line. In the first, it changes the linkage.


> Yes, you are right. I was not prepared to have yet more
> subtleties, especially such seemingly illogical ones. It's my
> fault I know, but I cannot understand why should const char
> array have different linkage than variable char array?
> Probably something to do with C legacy?


Well, nothing involving const is due to C legacy, since C++ had
const before C did. I'm pretty sure that the initial
modiviation for const affecting linkage is due to things like:

int const dim = 43 ;

In C++, `dim' has been a constant integral expression from the
day const was introduced (where as it is not a constant integral
expression in C, even today). To work as a constant integral
expression, of course, you need the initializer. And there are
a lot of constant integral expressions which you'll want in
header files as well. If the linkage of the above were external
(as it is in C, or without the const), you'd have to write:

static int const dim = 43 ;

if you wanted to avoid duplicate definitions. And while
personally, that doesn't bother me, apparently, it did bother
some early users, and the rule was made (very early) that const
variables default to internal linkage (i.e. as if they were
declared static).

All of this was long before templates, of course, so the fact
that you cannot use the address of dim as a template argument
wasn't considered, nor the fact that passing dim by reference in
a function template results in undefined behavior.

> OK, I can see some logic here, if the arrays are considered to
> be extension of a single object to case N>1, then it makes
> sense that extension of const/non-const object shares the same
> linkage as the single object. However, in almost all other
> contexts the array is equivalent to a pointer to a object - I
> think this is the source of my confusion.


An array is never really equivalent to a ponter to an object.
It converts to a pointer to the first element in some specific
cases, in expressions, but there is still a conversion involved.
A pointer designates an object; it is NOT that object, nor does
it contain that object. An array contains its members, and is
actually more like a struct than a pointer.

The fact remains that in:
int const array[ N ] ;
it is the "int" that is const, and not the array, so the const
isn't top level, and that at least in C, "If the specification
of an array type includes any type qualifiers, the element type
is so qualified, not the array type." So even if you write:
typedef int A[ N ] ;
A const array ;
at least in C, it is not a top level const (not that this makes
a difference in C). So strictly speaking, I don't think that
the array definition has top level const, according to the
standard. On the other hand, at least three compilers (Sun CC,
g++ and VC++) treat it as if it does.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
 
 
 
James Kanze
Guest
Posts: n/a
 
      05-26-2008
On May 26, 6:28 am, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
> * Paavo Helde:
> >> On May 24, 10:46 pm, Paavo Helde <(E-Mail Removed)> wrote:
> >>> "Stephen Howe" <sjhoweATdialDOTpipexDOTcom> kirjutas:
> >>>> 2) What about the last two statements with const missing and placed
> >>>> in a header file
> >>>> char SomeConst5[] = "A value 3";
> >>>> char *SomeConst6 = "A value 4";
> >>> The const you dropped is not the top-level one, so it does not
> >>> have any significance here.
> >> In the second line. In the first, it changes the linkage.


> > Yes, you are right. I was not prepared to have yet more
> > subtleties, especially such seemingly illogical ones. It's
> > my fault I know, but I cannot understand why should const
> > char array have different linkage than variable char array?
> > Probably something to do with C legacy?


> The two declarations shown above do not have top-level const.
> They provide assignable variables. Since they're assignable
> variables, not 'const', they have external linkage by default.


The real question here is:
char const SomeConst[] = "A value" ;
Does SomeConst have external linkage, or internal? Intuitively,
I would say internal (and g++, Sun CC and VC++ agree with me),
but I can't find anything in the standard to back this up. And
if this has internal linkage, how is it different from:
struct Toto
{
int const i ;
} ;
Toto x = { 43 } ;
In both cases, we have an agglomerate in which all elements are
const (but the agglomerate itself is not declared const).

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      05-27-2008
On May 26, 1:13 pm, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
> * James Kanze:
> > On May 26, 6:28 am, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
> >> * Paavo Helde:
> >>>> On May 24, 10:46 pm, Paavo Helde <(E-Mail Removed)> wrote:
> >>>>> "Stephen Howe" <sjhoweATdialDOTpipexDOTcom> kirjutas:
> >>>>>> 2) What about the last two statements with const missing and placed
> >>>>>> in a header file
> >>>>>> char SomeConst5[] = "A value 3";
> >>>>>> char *SomeConst6 = "A value 4";
> >>>>> The const you dropped is not the top-level one, so it does not
> >>>>> have any significance here.
> >>>> In the second line. In the first, it changes the linkage.


> >>> Yes, you are right. I was not prepared to have yet more
> >>> subtleties, especially such seemingly illogical ones. It's
> >>> my fault I know, but I cannot understand why should const
> >>> char array have different linkage than variable char array?
> >>> Probably something to do with C legacy?


> >> The two declarations shown above do not have top-level const.
> >> They provide assignable variables. Since they're assignable
> >> variables, not 'const', they have external linkage by default.


> > The real question here is:
> > char const SomeConst[] = "A value" ;
> > Does SomeConst have external linkage, or internal?


> Internal.


> It's const.


Well, that's what I think it should be, too. But I can't find
anything in the standard to back it up.

> > Intuitively,
> > I would say internal (and g++, Sun CC and VC++ agree with me),
> > but I can't find anything in the standard to back this up.


> §3.5/3 would apply if the object, the array, itself was
> declared const.


> But here it's seemingly the elements that are const, and
> seemingly that the array effective constness stems from arrays
> not being assignable on their own.


Exactly. In C, the standard says explicitly that there's no
such thing as a const array. The C++ standard doesn't say that
in so many words, but it does say that "Any type of the form
``cv-qualifier-seq array of N T'' is adjusted to ``array of N
cv-qualifier-seq T,[ ...]'', which means that even if you write:

typedef int A[10];
A const a ;

The type of a is array of 10 const int, and the const-ness is
not top level.

> There is however a non-normative note at the end of §8.3.4/1
> that attempts to explain this. Presumably what it's meant to
> explain is that the /intent/ of that paragraph is that
> cv-qualification of array elements transfer to the array
> object itself.


A very feeble attempt, IMHO. But perhaps sufficient if it were
normative.

> Anyway, it explicitly says "internal linkage".


Where?

> > And
> > if this has internal linkage, how is it different from:
> > struct Toto
> > {
> > int const i ;
> > } ;
> > Toto x = { 43 } ;
> > In both cases, we have an agglomerate in which all elements are
> > const (but the agglomerate itself is not declared const).


> cv-qualification of elements of a struct does not transfer to
> the struct itself.


I know, but according to the standard, the same is true of
arrays. Only more so, because you can't declare an object of
array type const.

Anyhow, I think it's all vague enough for me to raise an issue
with the committee. I'm not sure, but judging from the behavior
of the compilers I've tested, I think that there is more or less
a consensus that the const-ness of the array elements *should*
cause internal linkage (as if the array itself were const); it's
just a question of making this clear in the wording of the
standard.

With regards to the struct above: I rather like the idea that a
PODS in which all elements are const would cause objects of that
type to be const as well, but that would definitely be an
extention, or a change in the language (and it's probably not
important enough to bother with).

Only distantly relevant to the current discussion: I don't see
anything forbidding a union to contain a const object either,
e.g.:

union U { int const a; double b ; } ;

I don't quite see how it could work, however. (Unions are being
reworked in the current draft, to remove a lot of the
restrictions. I'm not sure how this affects const elements in
unions, however.)

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      05-28-2008
On May 27, 11:26 am, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
> * James Kanze:


> > On May 26, 1:13 pm, "Alf P. Steinbach" <(E-Mail Removed)> wrote:


> >> There is however a non-normative note at the end of §8.3.4/1
> >> that attempts to explain this. Presumably what it's meant to
> >> explain is that the /intent/ of that paragraph is that
> >> cv-qualification of array elements transfer to the array
> >> object itself.


> > A very feeble attempt, IMHO. But perhaps sufficient if it were
> > normative.


> >> Anyway, it explicitly says "internal linkage".


> > Where?


> <q>
> Note: an "array of N cv-qualifier-seq T" has cv-qualified type;
> </q>


> which I (now I see, explained below, probably incorrectly,
> although opinions differ) read as an attempted explanation
> that the element CV-qualification is transferred to the array
> object itself, and continues, emhpasis added


> <q>
> such an array has *internal linkage* unless explicitly declared 'extern'
> (7.1.5.1) and must be initialized as specified in 8.5.
> </q>


That'll teach me to only look at the latest draft for such
things. The second part you quote above has been dropped in the
latest draft. Which is curious, because of course, the only
real intention of this that I can see is to ensure internal
linkage.

> Of course if it were taken literally it would raise the issue
> of auto variables with internal linkage.


Maybe that's why it was dropped. Or more accurately, replaced
by "see 3.9.3". Which says in its paragraph 2: "Any
cv-qualifiers applied to an array type affect the array element
type, not the array type (8.3.4)." And we're back to where we
started.

> In the C++0x draft, at least my old version, the latter quoted
> part is removed, and instead there is a reference to §3.9.3
> about CV-qualification, where it's made clear that my
> interpretation above is not the one to be adopted in C++0x,


Except that "an `array of N cv-qualifier-seq T' has cv-qualified
type" seems to directly contradict "Any cv-qualifiers applied to
an array type affect the array element type, not the array
type". (The contradiction is in the "not the array type".)

So someone has been doing something, but it still looks like a
case of the left hand not knowing what the right hand is doing
to me. And quite frankly, I'd prefer that arrays of const T
behave as const array of const T. (Actually, I'd prefer that
const didn't affect the linkage, and that arrays behaved like
other composite types, i.e. with copy, no implicit conversion to
pointer, etc., etc. But it's far too late for either of those
changes.)

> Current and C++0x
> §3.9.3/2
> "Any cv-qualifiers applied to an array type affect the array
> element type, not the array type (8.3.4)."


> The change in §8.3.4/1 wording, removal of that part about
> internal linkage, follows core language Defect Report #112
> discussion,


> http://www.open-std.org/jtc1/sc22/wg...fects.html#112


> which touches on the linkage issue but does not resolve it or
> really discuss it (the only concern is that "volatile" should
> not result in internal linkage).


> Hm.


I see we're finding most of the same passages (although I'd
missed the DR).

> [snip]


> > Anyhow, I think it's all vague enough for me to raise an issue
> > with the committee. I'm not sure, but judging from the behavior
> > of the compilers I've tested, I think that there is more or less
> > a consensus that the const-ness of the array elements *should*
> > cause internal linkage (as if the array itself were const); it's
> > just a question of making this clear in the wording of the
> > standard.


> I agree, good idea.


I've done so, but I really miss csc++ for this. The committee
reflectors seem more adapted to something more concrete, after a
bit of preliminary discussion.

Anyway, while I'm not totally happy with the idea that arrays
behave differently from other composite types (all elements
const does not imply composite const), arrays behave differently
from other composite types in so many other ways, and in the
absence of anyway to declare an array const, I rather think that
the best (most intuitive) solution is for the cv-qualification
of the array to be exactly that of the cv-qualification of its
elements. (It isn't in C, but in practice, in C, it doesn't
matter, since the const-ness of the array would have no
practical effects.)

Anyway, we'll see what comes of it, but in the meantime, I
wouldn't count on it being any particular way in a given
compiler. If I think it might matter, I'll explicitly add a
static or an extern (depending on what I want).

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Header files with "header.h" or <header.h> ?? mlt C++ 2 01-31-2009 02:54 PM
const vector<A> vs vector<const A> vs const vector<const A> Javier C++ 2 09-04-2007 08:46 PM
Casting int'** to 'const int * const * const' dosn't work, why? Jonas.Holmsten@gmail.com C Programming 11 07-01-2007 06:16 PM
"const int" and "const char*" in header (.h) files C. J. Clegg C++ 4 03-28-2006 12:07 PM
Re: Declaration of "const A &B::A() const" changes meaning of A from "class A" Alexander Farber C++ 0 06-21-2005 07:35 AM



Advertisments