Not able to compile my C Project

Hi there,
as stated in the Topic, I can’t compile my C project. I believe it to be an issue with my project structure, which is as follows. I have 3 main directories “build”, “include”, and “src”. The *.c files are all located in “src” and the header *.h files are in “include”, the “build” should contain all the object and binary files (once i can compile them). So far so good. I’ve basically got a main.c and a helper.c furthermore there are some constants defined in customlib.h that are being used in both main.c and helper.c. Now i would like to have some structs (typedefed preferably), so I i thought with a “typedef struct my_type my_type” I could define it in the helper.h and have the actual body of the struct within the helper.c and that I would be able to use the typdef my_type in both customlib.c and main.c. But unfortunately the compiler throws an error when i call “sizeof(my_type)”. The message is "invalid application of ‘sizeof’ to incomplete type ‘my_type’. So I guess it doesn’t know the actual struct. Does the actual body of the struct need to be within the helper.h?

Thanks for reading and kind regards. RN

It’s a bit hard to do advice without any code to see. And without any info on build environment.

ISO/IEC 9899:201x §6.5.3.4 The sizeof and alignof operators

Constraints

  1. The sizeof operator shall not be applied to an expression that has function type or an incomplete type, to the parenthesized name of such a type, or to an expression that designates a bit-field member.

129) An incomplete type may only by used when the size of an object of that type is not needed.

So basically you can’t use sizeof on a opaque type. It needs to know its definition.

1 Like

Yeah Sorry. This are the relevant code snippets. And also project structure.

include/helper.h
include/customlib.h
src/helper.c
src/main.c

helper.h

#ifndef HELPER_H
#define HELPER_H

struct my_type
typedef struct my_type my_type

#endif

helper.c

#include "helper.h"
#include "customlib.h"

struct my_type{
int a;
int b;
int c;
}

main.c

#include "helper.h"
#include "customlib.h"

int main (int argc, char **argv)
{
size_t size;
size = sizeof(my_type);
}

the compiler command is

gcc -Wall -Iinclude -c src/main.c -o build/main.o

Thanks again for putting up.

Yeah, the main.c translation unit can’t use sizeof because it doesn’t have definition for my_type. If you do the preprocess main.c yourself you can see that:

struct my_type
typedef struct my_type my_type

// customlib.h goes here

int main (int argc, char **argv)
{
size_t size;
size = sizeof(my_type);
}

sizeof(my_type); should be a constant but cannot be emmited due to my_type not being defined in this TU

Hm, so helper.h should look like this?

#ifndef HELPER_H
#define HELPER_H

typedef struct my_type{
int a;
int b;
int c;
}
#endif

or is there some other way? I probably should look a bit more into what the compiler does…

typedef struct{
int a;
int b;
int c;
} my_type;

in the header will work. Since any TU will have that definition when they include the header.

Oh yeah totally forgot to name the typedef, should i bother naming the struct tho? Is there any convention?

You don’t need to name the struct if you don’t use it recursively. IE:

typedef struct my_type_s{
struct my_type_s* node;
int a;
int b;
int c;
} my_type_t;

Interesting, i shall dig deeper on what applications this implicates. For now though I will go on and try to finish this project. Which should go smoother now that it finally compiled, so thank you very much for this. Have a nice Day.

1 Like

Feel free to ask more, I am happy to help.

1 Like

BTW as for the

There are two schools, those who use typdefs and those who use struct/enum/union explicitly. The latter says it’s for readability, meaning the “object” is explicit coz you can see what it is right in the type.

Many like to use _t suffix to distinguish typedefs from other types, but AFAIK POSIX reserves that for themselves, so if you write POSIX compatible software, it’s wrong to do so.

Other than that, you can do whatever you like, as long as you are consistent throughout the project. IE, I know some people use PascalCase for types, and camelCase for functions and variables. Some people also use prefixes for global vars g_.

#define MY_MACRO
typedef struct { /* ... */ } MyStruct;

extern int g_globalVar;

void MyStruct_method(MyStruct* ms);
void globalFunc(void);

If you want a predefined style you can use, check Linux kernel style or GNU (don’t lol) or clang format (they also have a tool to auto style your code IIRC)


I personally use snake_case exclusively in C.

#define MY_MACRO
typedef struct { /* ... */ } my_struct_t;

extern int global_var;

void my_struct_method(my_struct_t* ms);
void global_func(void);

Thanks for the hints. Yeah I always try to keep my code consistent. and that _t explanation is also helpful since I currently am trying to be POSIX conform. I see there is much out there that still needs discovering on my part.

1 Like

Oh and one more thing. If you really want to hide the definition of the struct and use sizeof outside the implementation TU, you could just define a func that returns that :wink:

// header.h
struct  my_struct; 
typedef struct my_struct my_type;

size_t my_type_size(void);
// implementation.c
#include "header.h"

struct my_struct
{
    // ...
};

size_t my_type_size(void)
{
    return sizeof(my_type);
}

That way you can encapsulate the structure and still get its size. Pretty sure all modern compilers will inline that func anyways.