ChatGPT解决这个技术问题 Extra ChatGPT

Should struct definitions go in .h or .c file?

I've seen both full definitions of structs in headers and just declarations—is there any advantage to one method over the other?

If it makes a difference, I usually typedef a struct like so in the .h

typedef struct s s_t;

To be clear, the options are declaration in the header file and definition in the class, or both declaration and definition in the header file. Both should result in the same usability, even if one is by linkage, shouldn't they?

I see many almost duplicates, e.g. here but no exact matches. Please correct me if I'm wrong in this regard.

Do you want an opaque or non-opaque struct?
Side note, identifiers with _t are reserved by POSIX, so this is usually a bad idea. You could just do typedef struct toto toto.
I've seen lots of _t use other places (e.g., lighttp, linux) ... and I prefix things with projident_ so, that shouldn't be an issue should it?
And @WTP, I think that non-opaque is generally considered better and more Cish, no (what with the FILE example etc). So, non-opaque.
If it's a non-opaque struct, it has to go in a header file, or your code is not DRY (don't repeat yourself).

τ
τεκ

Private structures for that file should go in the .c file, with a declaration in the .h file if they are used by any functions in the .h .

Public structures should go in the .h file.


I think I agree with this answer more. It's not about using the struct through any other .c files or not, it's whether the struct should be considered public (and so, accessible) or not.
@τεκ Do you mean global and local visibility? public doesnt make sense in a struct. All structs are public by default.
@Geo Papas This is a question about C. public is not a keyword in C. If you look at Matthew Slattery's answer below you can see how using only a forward declaration in the header causes a compiler error when the user tries to use members of a private (opaque) struct.
M
Matthew Slattery

Both should result in the same usability, even if one is by linkage, shouldn't they?

No, not when you consider other .c files including the same header. If the definition of the structure is not visible to the compiler, the details of that definition cannot be used. A declaration without a definition (e.g. just struct s;) causes the compiler to fail if anything tries to look inside struct s, while still allowing it to e.g. compile struct s *foo; (as long as foo is not later dereferenced).

Compare these versions of api.h and api.c:

Definition in header:                 Definition in implementation:
+---------------------------------+   +---------------------------------+
| struct s {                      |   | struct s;                       |
|     int internal;               |   |                                 |
|     int other_stuff;            |   | extern void                     |
| };                              |   | api_func(struct s *foo, int x); |
|                                 |   +---------------------------------+
| extern void                     |   +---------------------------------+
| api_func(struct s *foo, int x); |   | #include "api.h"                |
+---------------------------------+   |                                 |
+---------------------------------+   | struct s {                      |
| #include "api.h"                |   |     int internal;               |
|                                 |   |     int other_stuff;            |
| void                            |   | };                              |
| api_func(struct s *foo, int x)  |   |                                 |
| {                               |   | void                            |
|     foo->internal = x;          |   | api_func(struct s *foo, int x)  |
| }                               |   | {                               |
+---------------------------------+   |     foo->internal = x;          |
                                      | }                               |
                                      +---------------------------------+

This client of the API works with either version:

#include "api.h"

void good(struct s *foo)
{
    api_func(foo, 123);
}

This one pokes around in the implementation details:

#include "api.h"

void bad(struct s *foo)
{
    foo->internal = 123;
}

which will work with the "definition in header" version, but not with the "definition in implementation" version, as in the latter case the compiler has no visibility of the layout of the structure:

$ gcc -Wall -c bad.c
bad.c: In function 'bad':
bad.c:5: error: dereferencing pointer to incomplete type
$

So, the "definition in implementation" version protects against accidental or deliberate misuse of private implementation details.


just want to know how you created those code windows and still have code highlighted inside them...manually? This OP seems to have left using stackoverflow :'( Can anyone else tell me....
Nice example! Thanks!
Thank you for such example! dereferencing pointer to incomplete type was exactly my case!
I would just like to add that not all publicly accessible structs are bad: you might for instance want to enable the user of your API to fill in data and send it in.
@Mahesha999, there's no magic there. SO highlights code even if u put garbage in it. Notice it trying to highlight the command line output later in the post.
n
nos

If the struct is to be used by other compilation units (.c files) , place it in the header file so you can include that header file wherever it is needed.

If the struct is only used in one compilation unit (.c file), you place it in that .c file.


J
Jonathan Wood

The point is, placing it in a header file allows you to use the structure (or any other definition) from multiple source files, just by including that header file.

But if you are sure it will only be used from one source file, then it really doesn't make any difference.


T
TofuBeer

I put them into the C file to make it more Object Oriented, see this article.