1

I have 3 source files: matrix.c, tetramino.c and learntris.c (which includes the headers tetramino.h and matrix.h, linking it with the respective files). I have a structure: struct tetramino that is need in all these files. After reading this question and its answers- How to use a defined struct from another source file?, I created a header file structure.h and now my files look like this:

In structure.h:

typedef struct tetramino  
{
  int type;
  char *p;
}tetramino;

In matrix.h:

#include"structure.h"
int print_matrix(void);
int clear_matrix(void);

In tetramino.h:

#include"structure.h"
int rotate(void);
int set_tetramino(void);

And finally, in the main learntris.c file contains:

#include"structure.h"
#include"matrix.h"
#include"tetramino.h"

Now, upon compiling them, I get these errors:

error: redefinition of 'struct tetramino'

and

error: conflicting types for 'tetramino'

Where is the problem?

Community
  • 1
  • 1
Nityesh Agarwal
  • 344
  • 1
  • 4
  • 13

4 Answers4

3

When you #include <structure.h> in all of your files, it includes them each time. This causes it to try to define the structure each time.

Use include guards to ensure that the header file will be included once.

#ifndef STRUCTURE_H
#define STRUCTURE_H

typedef struct tetramino  
{
  int type;
  char *p;
}tetramino;

#endif /* STRUCTURE_H */

It is suggested to use guards in all your header files, however this is not a must, but a very good practice.


As stated by Neroku, you could use #pragme once instead. Read more here.

Community
  • 1
  • 1
gsamaras
  • 66,800
  • 33
  • 152
  • 256
2

Besides guards, that other answers explain, it is not good practice to include .h files in .h files as you now cannot control the order in which they are included. Also, a change to a .h file can now result in all your c files needing recompilation, even if they are not affected by the change (that is, you create unnecesary dependencies).

You should have included structure.h only in the C files and then only when the C file needs to know about the structure.

Paul Ogilvie
  • 24,146
  • 4
  • 18
  • 39
  • "and then only when it needs to know about the structure"- can you please elaborate what you mean by this? – Nityesh Agarwal May 20 '17 at 12:51
  • "not good practice to include .h files"- then what exactly can these files contain? – Nityesh Agarwal May 20 '17 at 12:58
  • "cannot control the order in which they are included"- Isn't the file that is named first, included first too? I mean if I write `#include"structure.h"` before `#include"matrix.h"`, doesn't it mean that structure.h will get included before matrix.h? – Nityesh Agarwal May 20 '17 at 13:10
  • With "cannot control the order in which they are included" I mean that some C files may need a different order in which the .h files are included than other C files. – Paul Ogilvie May 20 '17 at 13:12
1

Every header file should have the following structure:

#ifndef TETRAMINO_STRUCTURE_H
#define TETRAMINO_STRUCTURE_H

struct tetramino { ... };

#endif

This means that the main part of the header file is only evaluated once. The name TETRAMINO_STRUCTURE_H consists of the project name, the file name and the trailing H, meaning header.

Second, since the function declarations don't need the tetramino type, you don't need to #include "structure.h" in them. You only need these lines in the corresponding .c files.

Roland Illig
  • 37,193
  • 10
  • 75
  • 113
  • 1
    "Every header file needs the following structure:" -- no. Although this is the most common use case, there are some good uses for headers without guard macros as well. –  May 20 '17 at 12:35
  • Agreed, my response is too simple. But when beginners follow this advice, it won't do much harm to them, therefore I thought it would be ok. – Roland Illig May 20 '17 at 12:38
  • 1
    it's good advice to beginners of course, I'd just rephrase it to something like "you should always use the following [...]", so it's not the "bad kind of simplification" (the one that makes it incorrect) :) –  May 20 '17 at 12:41
1

#include literally pastes the contents of the included file into the location of the #include directive. So in your example, you end up with 3 times the same structure declaration.

The canonic solution for this is guard macros:

#ifndef EXAMPLE_HEADER_FILE_H
#define EXAMPLE_HEADER_FILE_H

struct exampleStruct
{
    // ...
};

#endif

This way, only the first #include will actually paste the declaration, every consecutive #include will cause the preprocessor to skip the whole header because the guard macro is already defined.