Header problems

G

gamehack

Hi all,

Let me describe the problem. I've a header file util.h which contains
the following:
#ifndef UTIL_H_
#define UTIL_H_

const char DEF_TITLE[] = "My Title";

int num_chars(int num);
char* get_default_title(void);

#endif /* UTIL_H_ */

When I include the header from two or more files in complains that
DEF_TITLE is defined more than once: "multiple definition of
`DEF_TITLE`" is printed for both files which use DEF_TITLE. I cannot
understand why this happens since I've put the header guards. Platform
is MinGW 3.4.2 & Win XP Pro.

Regards
 
O

osmium

gamehack said:
Let me describe the problem. I've a header file util.h which contains
the following:
#ifndef UTIL_H_
#define UTIL_H_

const char DEF_TITLE[] = "My Title";

Header guards do not protect against multiple definitions. Each program
segment that includes this header gets exactly one definition for DEF_TITLE.
There should only be *type* definitions or variable *declarations* in a
header.

Change it to external (q.v.) which will demote it to a declaration. Put a
definition in one of the files where it makes sense.
 
M

Michael Mair

gamehack said:
Hi all,

Let me describe the problem. I've a header file util.h which contains
the following:
#ifndef UTIL_H_
#define UTIL_H_

const char DEF_TITLE[] = "My Title";

DEF_TITLE is a file scope identifier with external linkage.
It must not be used more than once as such in the whole
programme. So, if you #include "util.h" in more than one
translation unit, this thing breaks.
int num_chars(int num);
char* get_default_title(void);

#endif /* UTIL_H_ */

When I include the header from two or more files in complains that
DEF_TITLE is defined more than once: "multiple definition of
`DEF_TITLE`" is printed for both files which use DEF_TITLE. I cannot
understand why this happens since I've put the header guards.

Header guards protect against
-- a.h --
#include "b.h"
---------
-- b.h --
#include "a.h"
---------
and multiple definitions of types.

Consider

-- util.h --
#ifndef UTIL_H_
#define UTIL_H_

extern const char *DEF_TITLE;

int num_chars(int num);
char* get_default_title(void);

#endif /* UTIL_H_ */
------------
-- util.c --
#include "util.h"

const char *DEF_TITLE = "My Title";

.....
 
P

Pedro Graca

gamehack said:
Let me describe the problem. I've a header file util.h which contains
the following:
#ifndef UTIL_H_
#define UTIL_H_

const char DEF_TITLE[] = "My Title";

Why not

#define DEF_TITLE "My Title" /* no semicolon */
int num_chars(int num);
char* get_default_title(void);

#endif /* UTIL_H_ */

And then use it in your program as a constant string

/* ... */
char title1[] = DEF_TITLE;
char *title2 = NULL;
/* ... including allocating space for title2 ... */
strcpy(title2, DEF_TITLE);
/* ... */
printf("Title: %s\n", title2 ? title2 : DEF_TITLE);
/* ... */
 
M

Michael Mair

Pedro said:
gamehack said:
Let me describe the problem. I've a header file util.h which contains
the following:
#ifndef UTIL_H_
#define UTIL_H_

const char DEF_TITLE[] = "My Title";


Why not

#define DEF_TITLE "My Title" /* no semicolon */

int num_chars(int num);
char* get_default_title(void);

#endif /* UTIL_H_ */


And then use it in your program as a constant string

/* ... */
char title1[] = DEF_TITLE;
char *title2 = NULL;
/* ... including allocating space for title2 ... */
strcpy(title2, DEF_TITLE);
/* ... */
printf("Title: %s\n", title2 ? title2 : DEF_TITLE);
/* ... */

This
- does not protect you against inadvertently trying
to modify DEF_TITLE
- potentially wastes storage if "My Title" is stored
multiple times (e.g. once per translation unit, once
per function, once per use...)

String literals should be used with care.

Cheers
Michael
 
D

Dave Thompson

gamehack said:
Let me describe the problem. I've a header file util.h which contains
the following:
#ifndef UTIL_H_
#define UTIL_H_

const char DEF_TITLE[] = "My Title";

Header guards do not protect against multiple definitions. Each program
segment that includes this header gets exactly one definition for DEF_TITLE.

More specifically, each 'translation unit' = source file + includes.
There should only be *type* definitions or variable *declarations* in a
header.

Change it to external (q.v.) which will demote it to a declaration. Put a
definition in one of the files where it makes sense.
Just adding 'extern' (not 'external', and not replacing anything
already there) to a declaration with an initializer doesn't help; it's
still a definition. You need to declare with extern and no
initializer, and then (as you say) define in one t.u.

It may be a problem (or not) that in that scheme the declaration
extern const char DEF_TITLE [] ;
has unknown bound/size, whereas with the initializer it has a known
size from the initial value even though not explicitly written. If
this matters you can duplicate the value in each t.u. as
static const char DEF_TITLE [] = "Value";
(It is even possible, and certainly permitted though not required,
that the implementation might be clever enough to merge these.)


- David.Thompson1 at worldnet.att.net
 

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,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top