Multiple Inclusion Bug

I'm fairly certain this is a bug with the compiler, but just to be sure I am not making a silly mistake...

I have two files that include the same header file.

The header file looks like this:

#ifndef GYRO_H
#define GYRO_H

/*
This is a list of registers in the ITG-3200. Registers are parameters that 
determine how the sensor will behave, or they can hold data that represent the
sensors current status. To learn more about the registers on the ITG-3200, 
download and read the datasheet.
*/
char WHO_AM_I = 0x00;
char SMPLRT_DIV= 0x15;
char DLPF_FS = 0x16;
char GYRO_XOUT_H = 0x1D;
char GYRO_XOUT_L = 0x1E;
char GYRO_YOUT_H = 0x1F;
char GYRO_YOUT_L = 0x20;
char GYRO_ZOUT_H = 0x21;
char GYRO_ZOUT_L = 0x22;

/*
This is a list of settings that can be loaded into the registers.
DLPF, Full Scale Register Bits
FS_SEL must be set to 3 for proper operation
Set DLPF_CFG to 3 for 1kHz Fint and 42 Hz Low Pass Filter
*/
char DLPF_CFG_0 = 1<<0;
char DLPF_CFG_1 = 1<<1;
char DLPF_CFG_2 = 1<<2;
char DLPF_FS_SEL_0 = 1<<3;
char DLPF_FS_SEL_1 = 1<<4;

/*address of gyro on I2C*/
char itgAddress = 0x68;

/*write and read addressed on i2c for Gyro*/
void itgWrite(char address, char registerAddress, char data);
unsigned char itgRead(char address, char registerAddress);

/*get x, y, and z axis angular rates from gyro*/
int gyroReadX(void);
int gyroReadY(void);
int gyroReadZ(void);

#endif

Note the #ifndef/#define/#endif preprocessor directives.

Two files (myproject_gyrotest.ino and Gyro.cpp) include this "Gyro.h" via:

#include "Gyro.h"

I get the following errors when compiling:

myproject_gyrotest.cpp.o:(.data.itgAddress+0x0): multiple definition of `itgAddress'
Gyro.cpp.o:(.data.itgAddress+0x0): first defined here
c:/arduino/arduino-1.0.2-windows/arduino-1.0.2/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions

along with tons of other multiple inclusion problems.

I mean, am I being a complete idiot, or is this another compiler bug? (There are several other bugs with this Arduino compiler I have found the hard way that are documented elsewhere).

Compiler version: 1.0.2 Windows 7 (x86)

...or is this another compiler bug?

No.

Since two files include Gyro.h they each create a global char variable called "itgAddress".

Is that value a constant? If so you should write it as:

const char itgAddress = 0x68;

If the value needs to be an initialized variable you should change the header file to make that an external reference:

extern char itgAddress;

and in the file where it makes the most sense, define the variable and its value:

char itgAddress = 0x68;

#defines are only defined within the compilation unit. You want each compilation unit to have your header file included exactly once. You don't want to do anything that allocates memory in a header file.

WizenedEE:
You don't want to do anything that allocates memory in a header file.

In particular, change things like

char DLPF_FS_SEL_1 = 1<<4;

to

#define DLPF_FS_SEL_1 1<<4

so there isn't any memory allocation involved in your definitions.

I'd further recommend puttings the expression parenthesis, like this

#define DLPF_FS_SEL_1 (1<<4)

to make it a bit more robust.

(There are several other bugs with this Arduino compiler I have found the hard way that are documented elsewhere).

Care to shair what these are?

Grumpy_Mike:

(There are several other bugs with this Arduino compiler I have found the hard way that are documented elsewhere).

Care to shair what these are?

Google is your friend. Here's a sampling of some of my favorites:

http://code.google.com/p/arduino/issues/list?can=2&q=preprocessor&colspec=ID+Type+Status+Priority+Milestone+Owner+Summary&cells=tiles

Thanks, johnwasser, for the post. I have since changed all of my allocated variables to pound defines to avoid the problem I was having. I will take your advice in the future about using const and externs.

Though, this Google Code Archive - Long-term storage for Google Code Project Hosting. documented problem seems to be exactly what I've been fighting for a while.

While two files include "Gyro.h", the pre-processor directives should indicate to the compiler to only create one copy of Gyro.h and link the other files against it, which (I would think) prevent the multiple inclusion problem.

I will switch to my Ubuntu drive in a minute to see how gcc handles this situation.

desh:
Thanks, johnwasser, for the post. I have since changed all of my allocated variables to pound defines to avoid the problem I was having. I will take your advice in the future about using const and externs.

Though, this Google Code Archive - Long-term storage for Google Code Project Hosting. documented problem seems to be exactly what I've been fighting for a while.

While two files include "Gyro.h", the pre-processor directives should indicate to the compiler to only create one copy of Gyro.h and link the other files against it, which (I would think) prevent the multiple inclusion problem.

I will switch to my Ubuntu drive in a minute to see how gcc handles this situation.

.h files aren't compiled. The compiler literally replaces the #include line with the file you want to include, so the contents of the .h file exist in every compiled file (.c, .cpp, .ino, .pde) that includes it. The include guards (#ifndef... #define) prevent the contents of the .h file to be copied in twice, but it will still be copied in every compiled file that includes it.