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?
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
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.
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
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.
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_.
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)
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.
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