Questions about const

G

gw7rib

I was having linking errors when I put:

const LPCTSTR Main_window_name = _TEXT("Thingy_main_window");

in one file and

extern const LPCTSTR Main_window_name;

in another. I've since realised that this is because (in C++) consts
do not, by default, have external linkage. I've solved the problem by
inserting an "extern" in front of the first one. (LPCTSTR is
typedef'ed in the headers somewhere as a pointer to constant
"characters", and _TEXT is a macro to convert a string to the correct
form of characters.)

However, I still have a couple of nagging doubts. The first is, is it
OK to use consts both in and with typedefs? For instance, if I do:

typedef int i;
typedef const int ci;

then can I do whichever I choose of

const i b = 3;

and

ci c = 3;

to get a variable of type const int? I see from testing that

const ci d = 3;

is an error - including the consts twice.

My second question is that, normally, if one were to put "extern int
x;" in several files, you would need to also include a line "int x;"
in one of them. But with consts, it seems that every mention of them
can have the extern keyword. Is this correct?

Thanks for any help.
Paul.
 
V

Victor Bazarov

I was having linking errors when I put:

const LPCTSTR Main_window_name = _TEXT("Thingy_main_window");

in one file and

extern const LPCTSTR Main_window_name;

in another. I've since realised that this is because (in C++) consts
do not, by default, have external linkage. I've solved the problem by
inserting an "extern" in front of the first one. (LPCTSTR is
typedef'ed in the headers somewhere as a pointer to constant
"characters", and _TEXT is a macro to convert a string to the correct
form of characters.)

However, I still have a couple of nagging doubts. The first is, is it
OK to use consts both in and with typedefs? For instance, if I do:

typedef int i;
typedef const int ci;

then can I do whichever I choose of

const i b = 3;

and

ci c = 3;

to get a variable of type const int? I see from testing that

const ci d = 3;

is an error - including the consts twice.

The answer is "Yes, it's OK", and you've discovered it already,
haven't you?
My second question is that, normally, if one were to put "extern int
x;" in several files, you would need to also include a line "int x;"
in one of them. But with consts, it seems that every mention of them
can have the extern keyword. Is this correct?

The One Definition Rule has to be obeyed. Unless you initialise your
object, it's a declaration. Adding an initialiser converts your
statement into a definition. You need to have one and only one
definition for every object in your program.

Now, if all of your declarations of a built-in type object do not
have any initialisers, then they are all merely declarations and you
still need a definition (without the keyword "extern") unless you
add "= 0" to one of them.

V
 
J

James Kanze

(e-mail address removed) wrote:

[...]
The One Definition Rule has to be obeyed. Unless you
initialise your object, it's a declaration.

No. The rules aren't very consistent. And there is an
interaction between definition/declaratin and linkage which has
to be considered. For objects at namespace scope, unless the
object is declared extern *and* has no initialization, it is a
definition. Both conditions are necessary for it to only be a
declaration. Linkage is more complicated, and in the absense of
any explicit keywords concerning linkage, it depends on the top
level const of the object: if the top level type is const, the
linkage is internal; otherwise, it is external.

If you wanted to be really clear, you'd probably use a linkage
specifier, extern or static, on every declaration at namespace
level. In practice, however, I don't know of anyone who
actually does this (starting with myself).
Adding an initialiser converts your statement into a
definition.

Something like "int x;" at namespace scope is a definition. So,
for that matter, would be "int const x;", except that the
definition of an object with top level const requires an
initializer.
You need to have one and only one definition for
every object in your program.
Now, if all of your declarations of a built-in type object do
not have any initialisers, then they are all merely
declarations and you still need a definition (without the
keyword "extern") unless you add "= 0" to one of them.

That's not correct.
 
J

James Kanze

(e-mail address removed) wrote:
[...]
My second question is that, normally, if one were to put
"extern int x;" in several files, you would need to also
include a line "int x;" in one of them. But with consts, it
seems that every mention of them can have the extern
keyword. Is this correct?
The One Definition Rule has to be obeyed. Unless you
initialise your object, it's a declaration.

No. The rules aren't very consistent.

Just a quick summary:
int x01 ; // definition, external linkage
int x02 = 0 ; // definition, external linkage
int const x03 ; // illegal, def. of const wo init.
int const x04 = 0 ; // definition, internal linkage

extern int x05 ; // declaration, external linkage
extern int x06 = 0 ; // definition, external linkage
extern int const x07 ; // declaration, external linkage
extern int const x08 = 0 ; // definition, external linkage

static int x09 ; // definition, internal linkage
static int x10 = 0 ; // definition, internal linkage
static int const x11 ; // illegal, def. of const wo init.
static int const x12 = 0 ; // definition, internal linkage
at namespace scope, of course.
 
G

gw7rib

Just a quick summary:
           int          x01     ;   // definition, external linkage
           int          x02 = 0 ;   // definition, external linkage
           int const    x03     ;   // illegal, def. of const wo init.
           int const    x04 = 0 ;   // definition, internal linkage

    extern int          x05     ;   // declaration, external linkage
    extern int          x06 = 0 ;   // definition, external linkage
    extern int const    x07     ;   // declaration, external linkage
    extern int const    x08 = 0 ;   // definition, external linkage

    static int          x09     ;   // definition, internal linkage
    static int          x10 = 0 ;   // definition, internal linkage
    static int const    x11     ;   // illegal, def. of const wo init.
    static int const    x12 = 0 ;   // definition, internal linkage
at namespace scope, of course.

Thanks for that, James. I think it's all clear now...
Paul.
 
G

gw7rib

(snip)
The answer is "Yes, it's OK", and you've discovered it already,
haven't you?

Thanks for your answer, Victor. I had discovered that it would compile
without warning. However, sometimes things compile without warning and
turn out to have undefined behaviour; and sometimes the behaviour is
defined but there is the potential for other problems. So I thought I
would ask to check. Thanks for the reassurance.

Paul.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top