2

I keep getting a compiler issue when trying to use a struct I defined in a header file.

I have two files: main.c:

     #include <stdio.h>
     #include <stdlib.h>
     #include "node.h"

     int main(){
         struct NODE node;
         node.data = 5;
         printf("%d\n", node.data);
         return 0;
     }

as well as node.h:

#ifndef NODE
#define NODE
    struct NODE{
        int data;
        struct NODE *next;
    };

#endif

I was writing a small program to practice some modular programming in C, but I've been getting the following compiler error:

node.h:5:21: error: expected ‘{’ before ‘*’ token
         struct NODE *next;
                     ^

I got the main.c to compile and do what I would like it to do when I define the struct directly in the file main.c, but for some reason it won't work if I place the definition in a header file and then try to include it in main.c. It's very frustrating, and I'm sure it's a minor thing, but could someone please tell me why this isn't working? From what I've been reading, I should be able to do this, no?

Thanks a lot!

P. Gillich
  • 289
  • 1
  • 9
  • 3
    Change your include guard to something like `NODE_H_`. – StoryTeller - Unslander Monica Apr 28 '19 at 19:55
  • @StoryTeller why should changing the name in the include guard help this code compile? – P. Gillich Apr 28 '19 at 19:56
  • 3
    Because `#define NODE` means "replace any occurrence of the token`NODE` by nothing". For a header file `header.h`, normal conventions for the header guard include `HEADER_H` or `HEADER_H_INCLUDED` — and you'll see system headers using leading underscores, but they're required to do that and you're required NOT to do that. – Jonathan Leffler Apr 28 '19 at 19:57
  • 2
    Because your struct has the same name as the your include guard `#define`, so the preprocessor is expanding it into an empty string. – Pierce Griffiths Apr 28 '19 at 19:57
  • As my fellows explained, this is why the header definition needs to be more unique than others. Always define your headers with unique suffix such as ```_H_``` or whatever you like. – Adir Ratzon Apr 28 '19 at 20:00
  • 2
    Note that you should not, in general, create function, variable, tag or macro names that start with an underscore. Part of [C11 §7.1.3 Reserved identifiers](https://port70.net/~nsz/c/c11/n1570.html#7.1.3) says: — _All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use._ — _All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces._ See also [What does double underscore (`__const`) mean in C?](https://stackoverflow.com/a/1449301) – Jonathan Leffler Apr 28 '19 at 20:01

2 Answers2

6

The preprocessor is expanding NODE to nothing because you've defined it with a macro. Change your header file to look like this:

#ifndef NODE_H
#define NODE_H
    struct NODE{
        int data;
        struct NODE *next;
    };

#endif
Pierce Griffiths
  • 733
  • 3
  • 15
3

You defined a macro NODE as nothing. From that point on, every NODE in your source code is replaced with nothing. So your header file is actually:

struct{
    int data;
    struct *next;
};

That should answer your question why changing the include guard from NODE to NODE_H fixes it.

gnasher729
  • 51,477
  • 5
  • 75
  • 98