4

I'm in trouble with the Warning redefinition of struct. To explain my problem I will consider 4 files.

  • Interface.c
  • Parser.h
  • Auth.h
  • Info.h

Interface.c

    #include "Auth.h"
    #include "Info.h"

/* some code here */

Parser.h

struct ParsedAuthResponse {
   char *name;
   char *key;
};

struct ParsedInfoResponse {
   char *name;
   char *message;
};
void auth_parser(char* serverResponse,struct ParsedAuthResponse *response_a);
void scrobble_parser(char* serverResponse, int* scrobbleParsedparsedResponse);
void love_unlove_parser(char* serverResponse, int* loveUnloveParsedResponse);
void getInfo_parser(char* serverResponse,struct ParsedInfoResponse *responseP);

Auth.h

#include "parser.h"
functionX(int a, struct ParsedAuthResponse *response);
/* some code here */

Info.h

#include "parser.h"
functionY(int a, struct ParsedInfoResponse *response);
/* some code here */

When I don't include Info.h or Auth.h in Interface.c there is no problem.

W.draoui
  • 383
  • 2
  • 3
  • 15
  • 5
    Is it the full code of Parser.h ? If so you need to add something that prevents you from including it twice, like this : `#ifndef PARSER_H #define PARSER_H [...] #endif` . This is because each time you write `#include "parser.h"` your header will very simply be copy-pasted at this location. If you do it twice, without this #ifndef preprocessor guard, then you effectively declare the structure twice. – Tim Jun 21 '17 at 10:45
  • No I will put the full parser.h. I can't for other files because they are very long. Can you now tell me how to correct the problem because I think what you are saying makes a lot of sense but i dont understand it very well – W.draoui Jun 21 '17 at 10:46
  • @P0W It is a duplicate, but I think this question demonstrates the problem much more clearly. It may be that your found duplicate should be closed with a link to this one, and not the other way around. – Lundin Jun 21 '17 at 10:50
  • @Lundin five year old post duplicate of future post :D I have removed my vote though. – P0W Jun 21 '17 at 10:53
  • @P0W Yes. The age is completely irrelevant when determining which post to close. We are only concerned with the quality of the questions and the answers. Given any number of duplicates, the best one should be preserved. Not the oldest one. – Lundin Jun 21 '17 at 10:56
  • @P0W Why not? :D – W.draoui Jun 21 '17 at 10:56
  • As it turns out, we do need a canonical duplicate for this very question, as it is a FAQ. The linked one is not good, the question there is too specific and the answers don't explain _why_ the error appears. – Lundin Jun 21 '17 at 10:58
  • Related: https://stackoverflow.com/q/27810115/694576 – alk Jun 21 '17 at 10:59

2 Answers2

7

You need to add a guard that prevents Parser.h to be included twice, like this :

#ifndef PARSER_H
#define PARSER_H
struct ParsedAuthResponse {
   char *name;
   char *key;
};

struct ParsedInfoResponse {
   char *name;
   char *message;
};
void auth_parser(char* serverResponse,struct ParsedAuthResponse *response_a);
void scrobble_parser(char* serverResponse, int* scrobbleParsedparsedResponse);
void love_unlove_parser(char* serverResponse, int* loveUnloveParsedResponse);
void getInfo_parser(char* serverResponse,struct ParsedInfoResponse *responseP);
#endif

Because each time you write the instruction #include "Parser.h" the content of Parser.h will simply be copy-pasted at the include location. This means that you will have both structures declared twice.

With the ifndef you prevent it from being copy-pasted more than once.

Tim
  • 1,853
  • 2
  • 24
  • 36
  • 1
    FYI, in case it's not clear, you should do this for every header file (with a different `#define` name obvs). in fact most programmers configure their editor to automatically add such in whenever they create a new header file. – Toby Jun 21 '17 at 11:07
2

The problem here is that during compilation, interface.c + all its included headers form a "translation unit". But since two of the headers both include parser.h, it will appear as if the contents in that header is declared twice.

To avoid problems like these, you should always use so-called "header guards" in every single header file you write:

#ifndef PARSER_H  // header guard
#define PARSER_H

struct ParsedAuthResponse {
   char *name;
   char *key;
};

struct ParsedInfoResponse {
   char *name;
   char *message;
};

...

#endif // PARSER_H

This ensures that the contents are only visible once per translation unit.

Lundin
  • 195,001
  • 40
  • 254
  • 396