1

I have declared a typedef struct on header files as follows:

myheader.h

typedef struct mystruct mystruct;

myheader.c

typedef struct mystruct{
    double *ptr1;
    double *ptr2;
    int *ptr3;
    mystruct *ptr4;
    mystruct *ptr5;
}mystruct;

program.c

#include "myheader.h"
int main()
{
mystruct *A = (mystruct *)malloc(sizeof(mystruct));
} 

when i try to compile using:

gcc -o myprogram myprogram.c myheader.c

i get the following error:

error: invalid application of ‘sizeof’ to incomplete type ‘mystruct’ {aka ‘struct mystruct’}

    mystruct * A = (mystruct *)malloc(sizeof(mystruct));


Is there something wrong with my code or am I compiling in the wrong way?

xaostheory
  • 81
  • 5
  • 2
    Please put the `struct` definition in the header file `myheader.h`. The `program.c` does not know its size. – Weather Vane Oct 29 '19 at 17:24
  • 1
    `myheader.c`? Header is header, `*.c` is not a header. `myprogram.c` does not see the `struct` definition, so the compiler can't know its size. – Eugene Sh. Oct 29 '19 at 17:25
  • How would `sizeof` (and the compiler) know the size of the structure if it doesn't have the definition (all fields) of the structure? – Some programmer dude Oct 29 '19 at 17:25
  • 1
    @Someprogrammerdude: It could know the size of the structure the same way it knows the addresses of functions: It puts a reference to the size of the structure in the object module, and the linker resolves that reference. That is not current practice, but it is theoretically possible, which shows the error of trying to teach people by asking rhetorical questions. The question presumes knowledge that **you have** that things are not done this way, but it is not actually impossible to do things that way, so the question cannot teach because it does not present an actual reason against this code. – Eric Postpischil Oct 29 '19 at 17:28
  • Now is probably a very good time to learn about the concept of [*translation units*](https://en.wikipedia.org/wiki/Translation_unit_(programming)). The C compiler only works on translation units (basically a single source file and all its included header files). It knows *nothing* about any other translation units or source files. – Some programmer dude Oct 29 '19 at 17:28
  • On an unrelated note, in C you [don't have to (and shouldn't really) cast the result of `malloc`](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – Some programmer dude Oct 29 '19 at 17:31
  • @Someprogrammerdude: The compiler does know things about other translation units. We tell it with `extern` declarations. – Eric Postpischil Oct 29 '19 at 18:25

1 Answers1

2

As @someprogrammerdude has already pointed out in his comment about translation units: when the compiler compiles main.c it has only knowledge about main.c and the included headers. So all it knows is that that there is a struct typedefed as mystruct but it knows nothing about its content and thus cannot determine ts size either, so you cannot use sizeof(). For the same reason you couldn't access any struct members, int *p = mystruct->ptr3; or mystruct->ptr1 = &mydouble; wouldn't compile as well.

Nevertheless that design is quite common. Let's assume you want to encapsulate every access to mystruct in an OO like manner. Then you have a source, say mystruct.c where you actually define the structure (like you did in myheader.c) and provide all neccessary getter and setter functions (including an allocation function). Then in every other source you could pass struct pointers any way you like but for everything else you have to use the designated functions.

The advantage of that approach is that in the future you're free to modify the struct whithout having to recompile every source that uses it.

Ingo Leonhardt
  • 9,435
  • 2
  • 24
  • 33