-4

I have the below project structure:

file - a.h

#pragma once

 struct best_fit_struct {
    void *next;
    size_t size;
};

file - b.h

#pragma once
typedef struct mm_t {
  int type;
  union {
      struct best_fit_struct best_fit_mm;
  } per_mm_struct;
  void *memory;
} mm_t;

file - b.c

#include "a.h"
#include "b.h"

on compiling b.c using gcc -c b.c, it throws the following error

file best_fit_mm has incomplete data type

I have included a.h before b.h, so the ordering looks proper to me.

Surprisingly, if I include a.h inside b.h, things gets resolved.

ffff
  • 2,853
  • 1
  • 25
  • 44
  • @SouravGhosh corrected the typo in the question – ffff Dec 23 '16 at 18:41
  • Are "a.h" and "b.h" complete files? Are there no guards? – peper0 Dec 23 '16 at 18:43
  • @peper0 I have used #pragma once in both of them – ffff Dec 23 '16 at 18:43
  • 4
    "so I dont want a.h to be included in it." - Not going to happen because of the error you're getting. How is the compiler to know how big to make the `union` if it doesn't have the definition of `struct a`? – Dark Falcon Dec 23 '16 at 18:44
  • 1
    ok realized that it is inevitable. @DarkFalcon but excluding that point, the compilation should be successful right? – ffff Dec 23 '16 at 18:45
  • There is missing semicolon after struct B. Is it just a typo in the question? – peper0 Dec 23 '16 at 18:45
  • @peper0 typo. corrected – ffff Dec 23 '16 at 18:46
  • 2
    @FaizHalde: No, not unless you `#include "a.h"`. You can't just exclude that point. It is a rule of how the compiler works. It *cannot* compile without the definition of `struct a` no matter what. – Dark Falcon Dec 23 '16 at 18:47
  • That's two typos in the question so far. Could you copy/paste your [MCVE], please? – Lightness Races in Orbit Dec 23 '16 at 18:48
  • Compiles for me :) Are you sure you posted _exactly_ what you are trying to compile? If so, whats the output of `gcc --version`? – peper0 Dec 23 '16 at 18:48
  • @DarkFalcon I mean excluding the public interface point – ffff Dec 23 '16 at 18:48
  • 3
    "Surprisingly, if I include a.h inside b.h, things gets resolved." <-- Then you answered your own question. – Dark Falcon Dec 23 '16 at 18:49
  • @DarkFalcon true. but why including a.h in b.c not compiling? – ffff Dec 23 '16 at 18:50
  • @FaizHalde is right that it's not a good style if you make headers not self-sufficient. You should not expect that someone include some header before another one. However it's true that if you include them in proper order it should compile. – peper0 Dec 23 '16 at 18:50
  • @peper0 good guideline :) its been a horrible experience with code dependency in c – ffff Dec 23 '16 at 18:51
  • 2
    @FaizHalde, since it works for me, there is something you probably have not told us. Did you use gcc's `-E` flag to run only the preprocessor and look at the result to ensure that the includes are working as expected? I would bet that something else is including `b.h` before `a.h`. – Dark Falcon Dec 23 '16 at 18:52
  • @DarkFalcon updated the question with actual contents – ffff Dec 23 '16 at 18:55
  • ``size_t`` is not declared. Could you post a zip file with something that compiles and another zip with something that doesn't compile? – peper0 Dec 23 '16 at 18:58
  • @FaizHalde: Now what is `data_id`? – MayurK Dec 23 '16 at 18:58
  • @peper0 haha. just #include . – ffff Dec 23 '16 at 19:00
  • 2
    Sorry guys. It was indeed an absence of a header file causing the issue. It's resolved. thanks! I should've posted my main.c file which only included the b.h file – ffff Dec 23 '16 at 19:08
  • @FaizHalde "using gcc -c b.c, it throws the following error" `file best_fit_mm has incomplete data type` and "It was indeed an absence of a header file causing the issue. ... I should've posted my main.c file" does not add up. – chux - Reinstate Monica Dec 23 '16 at 20:04

2 Answers2

2

The compiler has to know the entire layout of each data type. E.g. each field in aggregates, its offset (see offsetof), its size (see sizeof), its alignment (see alignof) and its type.

So the compiler needs to know all of struct a (all the fields there) to figure out the layout of struct b (and that should be known at the definition point of struct b).

In practice, you'll better add #include "a.h" near the start of your header b.h. Of course you want to add include guards in your header files.

BTW, my preference is to avoid having many small headers, and I prefer have a few large ones, perhaps even one single common header for a small project (which you might pre-compile with gcc, see this answer)

Sometimes, to debug preprocessor related bugs, you might ask to get the preprocessed form (e.g. using gcc -C -E source.c > source.i then look with an editor or pager inside source.i).

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
0

If file b.h uses items form file a.h then you must, by definition, include a.h within b.h

Dellowar
  • 3,160
  • 1
  • 18
  • 37
  • 1
    I'd like to comment on my own post: This does not answer OP's question.To my understanding `#include` is suppose to be a copy and paste. And if they are both copied and pasted in order in the .c file, why does it refuse to compile right? When the exact same thing is supposed to happen when `a.h` is included inside of `b.h`? – Dellowar Dec 23 '16 at 19:04