array in include

S

Salvatore Di Fazio

Hi,
I've an array in an include that is used everywhere in the project.

So to avoid the problem of declaration I made the following solution:

ifndef __UNWALKABLETILES__
#define __UNWALKABLETILES__

#define UNWALKABLETILES 16 /*!< Number of elements in UnwalkableTiles
array. */

/** List of unwalkable tiles. */
char rgUnwalkableTiles[] =
{
18, 19, 20, 21, 22, 23, 24, 25, 55, 56, 57, 60, 61, 62, 63, 64
};
#endif

But it doesn't works.
Why?
Tnx
 
E

Eric Sosman

Salvatore said:
Hi,
I've an array in an include that is used everywhere in the project.

So to avoid the problem of declaration I made the following solution:

ifndef __UNWALKABLETILES__
#define __UNWALKABLETILES__

#define UNWALKABLETILES 16 /*!< Number of elements in UnwalkableTiles
array. */

/** List of unwalkable tiles. */
char rgUnwalkableTiles[] =
{
18, 19, 20, 21, 22, 23, 24, 25, 55, 56, 57, 60, 61, 62, 63, 64
};
#endif

Your program's modules can *declare* rgUnwalkableTiles[]
as often as you like, but must *define* it exactly once. The
usual way of doing this is to put the declaration in a header
file that you #include in all the source modules:

/* tiles.h */
#define UNWALKABLETILES 16
extern char rgUnwalkableTiles[UNWALKABLETILES];

.... and then place the definition in exactly one source file:

/* somefile.c */
#include "tiles.h"
char rgUnwalkableTiles[] = { ... as above ... };

Note that somefile.c #includes tiles.h; this is a very
good idea because it lets the compiler "see" the declaration
and the definition at the same time, which means it can detect
any inadvertent mis-matches.
 
K

Keith Thompson

Salvatore Di Fazio said:
I've an array in an include that is used everywhere in the project.

So to avoid the problem of declaration I made the following solution:

ifndef __UNWALKABLETILES__
#define __UNWALKABLETILES__

#define UNWALKABLETILES 16 /*!< Number of elements in UnwalkableTiles
array. */

/** List of unwalkable tiles. */
char rgUnwalkableTiles[] =
{
18, 19, 20, 21, 22, 23, 24, 25, 55, 56, 57, 60, 61, 62, 63, 64
};
#endif

But it doesn't works.
Why?

Eric Sosman already answered the question you asked, so I'll answer
some questions you didn't ask.

Include guards are an excellent idea, but you should avoid identifiers
starting with underscores; many of them are reserved to the
implementation. (There are rules that depend on whether the second
character is another underscore, an upper case letter, or a lower case
letter, but it's not really worth remembering the details.)

If the include guard is supposed to refer to the header, a good
convention is "H_" followed by the header name; for example:

#ifndef H_UNWALKABLETILES
#define H_UNWALKABLETILES
....
#endif

Also, long run-on identifiers like UNWALKABLETILES are difficult to
read. I suggest changing it to UNWALKABLE_TILES.
 
S

Salvatore Di Fazio

Eric said:
Your program's modules can *declare* rgUnwalkableTiles[]
as often as you like, but must *define* it exactly once.

Why?
I don't must define it exactly ...
The usual way of doing this is to put the declaration in a header
file that you #include in all the source modules:

/* tiles.h */
#define UNWALKABLETILES 16
extern char rgUnwalkableTiles[UNWALKABLETILES];

... and then place the definition in exactly one source file:

/* somefile.c */
#include "tiles.h"
char rgUnwalkableTiles[] = { ... as above ... };

Note that somefile.c #includes tiles.h; this is a very
good idea because it lets the compiler "see" the declaration
and the definition at the same time, which means it can detect
any inadvertent mis-matches.

But I prefere keep it in a header file.

Tnx
 
F

Flash Gordon

Salvatore said:
Eric said:
Your program's modules can *declare* rgUnwalkableTiles[]
as often as you like, but must *define* it exactly once.

Why?
I don't must define it exactly ...

You must define it exactly once because that is how C is defined.
The usual way of doing this is to put the declaration in a header
file that you #include in all the source modules:

/* tiles.h */
#define UNWALKABLETILES 16
extern char rgUnwalkableTiles[UNWALKABLETILES];

... and then place the definition in exactly one source file:

/* somefile.c */
#include "tiles.h"
char rgUnwalkableTiles[] = { ... as above ... };

Note that somefile.c #includes tiles.h; this is a very
good idea because it lets the compiler "see" the declaration
and the definition at the same time, which means it can detect
any inadvertent mis-matches.

But I prefere keep it in a header file.

The only way to do that is to use horrid tricks. Or use a language other
than C.
 
E

Eric Sosman

Salvatore Di Fazio wrote On 07/19/06 14:40,:
Eric Sosman wrote:

Your program's modules can *declare* rgUnwalkableTiles[]
as often as you like, but must *define* it exactly once.


Why?
I don't must define it exactly ...

I misspoke: You do not need to define the array at all --
provided you never use it. Section 6.9, paragraph 5:

[...] If an identifier declared with external linkage
is used in an expression (other than as part of the
operand of a sizeof operator whose result is an integer
constant), somewhere in the entire program there shall
be exactly one external definition for the identifier;
otherwise, there shall be no more than one.

So if you intend to use any of the values in rgUnwalkableTiles[]
you must provide exactly one definition of the array; exactly
one compiled module must contain the array's definition. (If
you don't use the array, it's all right not to define it at all
but you still mustn't define it twice.)
The usual way of doing this is to put the declaration in a header
file that you #include in all the source modules:

/* tiles.h */
#define UNWALKABLETILES 16
extern char rgUnwalkableTiles[UNWALKABLETILES];

... and then place the definition in exactly one source file:

/* somefile.c */
#include "tiles.h"
char rgUnwalkableTiles[] = { ... as above ... };

Note that somefile.c #includes tiles.h; this is a very
good idea because it lets the compiler "see" the declaration
and the definition at the same time, which means it can detect
any inadvertent mis-matches.


But I prefere keep it in a header file.

Too bad. You can play games with macros so your single
header file compiles one way in one file and a different way
in all the others, but that's just a subterfuge.

"I accept the Universe." -- Margaret Fuller
"Gad! She'd better!" -- Thomas Carlyle
 
S

Salvatore Di Fazio

Eric Sosman ha scritto:
I misspoke: You do not need to define the array at all --
provided you never use it. Section 6.9, paragraph 5:
okkey

Too bad. You can play games with macros so your single
header file compiles one way in one file and a different way
in all the others, but that's just a subterfuge.

So you suggest to me to no't put all the defines in one header but
divide these in the correct header file?

Another question, if I've something like it

-- myheader.h --
#ifndef H_MY_HEADER_
#define H_MY_HEADER_
#define A 12
#endif


-- myfirst.c --
#include <myheader.h>
....


-- mysecond.c --
#include <myheader.h>


the compiler defines twice the A?
 
S

Salvatore Di Fazio

Eric Sosman ha scritto:
I misspoke: You do not need to define the array at all --
provided you never use it. Section 6.9, paragraph 5:
okkey

Too bad. You can play games with macros so your single
header file compiles one way in one file and a different way
in all the others, but that's just a subterfuge.

So you suggest to me to no't put all the defines in one header but
divide these in the correct header file?

Another question, if I've something like it

-- myheader.h --
#ifndef H_MY_HEADER_
#define H_MY_HEADER_
#define A 12
#endif

-- myfirst.c --
#include <myheader.h>
....

-- mysecond.c --
#include <myheader.h>

the compiler defines twice the A?

I wrote this question because I don't understand why the array was
multiple-defineted in all the files that include the myheader.h
 
T

Thomas J. Gritzan

Salvatore said:
Another question, if I've something like it

-- myheader.h --
#ifndef H_MY_HEADER_
#define H_MY_HEADER_
#define A 12
#endif

-- myfirst.c --
#include <myheader.h>
...

-- mysecond.c --
#include <myheader.h>

the compiler defines twice the A?

I wrote this question because I don't understand why the array was
multiple-defineted in all the files that include the myheader.h

Well,

1) With #define you define a preprocessor macro,
2) With

extern char rgUnwalkableTiles[UNWALKABLETILES];

you declare (means: tell the compiler that there is a rgUnwalkableTiles
and what type it hat, anywhere in any other file) the variable,

3) with

char rgUnwalkableTiles[] = { 1, 2, 3, ... };

you declare and define (means: tell the compiler, what rgUnwalkableTiles
actually is, what values it has) the variable.

You can do as many of 2) as you like in different compilation files (*.c
files) with the same name, but only one of 3) with the same name in all
compilation units that are linked together.

Macros you define with #define are another thing.
 
M

Mark McIntyre

Eric Sosman ha scritto:


So you suggest to me to no't put all the defines in one header but
divide these in the correct header file?

Another question, if I've something like it

-- myheader.h --
#ifndef H_MY_HEADER_
#define H_MY_HEADER_
#define A 12
#endif


-- myfirst.c --
#include <myheader.h>
...


-- mysecond.c --
#include <myheader.h>


the compiler defines twice the A?

A is never defined at all. Its a macro, and a text substitution takes
place very early on in the translation, so that every occurence of "A"
is replaced by "12" long before the compiler starts creating objects.

If you had put
int x ;
int y=3;
into the header, x would have been fine (you have two declarations)
but y would have generated an error at link time (you have two
definitions of it).


--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
M

Mark McIntyre

Eric Sosman ha scritto:


So you suggest to me to no't

Information: there is no apostrophe in "not"
put all the defines in one header but
divide these in the correct header file?

What we're saying is that you must *define* an object in a source
file, but you can declare it in a header.

Note that #define does NOT define an object, it creates a macro.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
M

Morris Dovey

Salvatore Di Fazio (in
(e-mail address removed)) said:

| I've an array in an include that is used everywhere in the project.
|
| So to avoid the problem of declaration I made the following
| solution:
|
| ifndef _UNWALKABLETILES_
| #define _UNWALKABLETILES_
|
| #define UNWALKABLETILES 16 /*!< Number of elements in
| UnwalkableTiles array. */
|
| /** List of unwalkable tiles. */
| char rgUnwalkableTiles[] =
| {
| 18, 19, 20, 21, 22, 23, 24, 25, 55, 56, 57, 60, 61, 62, 63, 64
| };
| #endif

Salvatore...

A better method might be to place this array declaration into a
separate .c source file, so that changes only require relinking rather
than re-compiling all sources that contain references; and so that all
modules can reference a single common array.
 
S

Salvatore Di Fazio

Morris said:
A better method might be to place this array declaration into a
separate .c source file, so that changes only require relinking rather
than re-compiling all sources that contain references; and so that all
modules can reference a single common array.

Thank you Morris
 

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
474,184
Messages
2,570,979
Members
47,579
Latest member
CharaS3188

Latest Threads

Top