3 ms·
typedef all structs - yes, helps with conciseness. Use typedefs liberally, I say. But only typedef the things themselves, not pointers to the things. You can al
by hyc_symas 3y ago
typedef all structs - yes, helps with conciseness. Use typedefs liberally, I say. But only typedef the things themselves, not pointers to the things. You can always use (type *) when you need a pointer. In particular, for function pointers, typedef the function, not the function pointer. Then you can use the function typedef for function declarations too, which gives you parameter type checking without needing to fix declarations everywhere if you change a function signature. I see most C codebases get this one wrong, typedef'ing the function pointer and still needing to manually write out all function declarations for that pointer definition.
I'm not sold on the structs as return types thing. I prefer just a numeric error code as a return value, and out parameters for any other returns.
- jpcfl 3y agoI prefer to use typedef's for opaque structs to emulate classes with all private fields, and use 'struct' for plain ol' data structures. Classes should only be accessed via functions, while structs can be accessed directly. I think this is more-or-less a C/POSIX standard convention. E.g., `pthread_t` vs. `struct stat`.
- lelanthran 3y ago> I prefer to use typedef's for opaque structs to emulate classes with all private fields, and use 'struct' for plain ol' data structures. Classes should only be accessed via functions, while structs can be accessed directly. Totally agree, I even wrote this as a blog post: https://www.lelanthran.com/chap9/content.html https://www.lelanthran.com/chap9/content.html
- yvdriess 3y agoIt's definitely part of the linux kernel coding style: https://www.kernel.org/doc/html/v4.10/process/coding-style.html#typedefs https://www.kernel.org/doc/html/v4.10/process/coding-style.h...
- Warwolt 3y agoThat's all fine, but you cannot have nicely behaved stack allocated structs and use the data hiding method outlined in that blog post, which I think is a pretty big caveat
- jpcfl 3y agoYes, allowing clients to control allocation of a struct is a crucial feature of any C API, especially if it's going to be used on embedded targets where heap is unavailable or restricted. The pattern I like to use for this is to expose class definitions, and declare each field with an underscore suffix to indicate it's private. typedef struct Foo { int x_; // implementation detail. don't touch. } Foo; Another pattern I've seen for this is to use truly opaque structs of byte arrays, that are then typecast into the proper struct in the implementation. // foo.h #define FOO_SIZE_ 4 #define FOO_ALIGN_ 4 typedef struct Foo { _Alignas(FOO_ALIGN_) char impl_[FOO_SIZE_]; } Foo; // foo.c #include "foo.h" typedef struct FooImpl { int x; } FooImpl; _Static_assert(FOO_SIZE_ == sizeof(FooImpl), ""); _Static_assert(FOO_ALIGN_ == _Alignof(FooImpl), ""); void Foo_bar(Foo const* self_opaque) { FooImpl const* self = (FooImpl)self_opaque; ... } I'm not a big fan of this approach, but it does protect your clients against themselves.
- PH95VuimJjqBqy 3y ago> But only typedef the things themselves, not pointers to the things. I agree with this. One of the things I dislike about SDL_net, etc, is they do exactly what you're describing. It's a pointer but they typedef it as if it's a value type. I understand the intent but imo that's very icky.