Is it good practice to hide the definition of a structure in C?

I think hiding the definition of the structure makes the code more secure, because you use it with a compiler, which no member of the structure can access directly. The disadvantage is that users cannot declare structure type variables on the stack because the size of the structure is unknown, and sometimes it is advisable to avoid using malloc() . It can be (with partial success) using alloca(3) , which is present in all major libc implementations, although this function does not match POSIX. Given these small pros and cons, can such a design be considered good at all?

In lib.h :

 struct foo; extern size_t foo_size; int foo_get_bar (struct foo *); 

In lib.c :

 struct foo { int bar; }; size_t foo_size = sizeof foo; int foo_get_bar (struct foo *foo) { return foo->bar; } 

In example.c :

 #include "lib.h" int bar(void) { struct foo *foo = alloca (foo_size); foo_init (foo); return foo_get_bar (foo); } 

UPD . Updated a question that indicates that the idea of ​​using alloca() is to declare a structure on the stack, but hiding its definition.

+8
c memory-management struct alloca
source share
2 answers

Yes, it is good practice to hide data.

Alternative to alloca(foo_size); is declaring an aligned array of characters and performing a pointer conversion.

Pointer conversion is not fully portable.

The character array must be a VLA if the size should be a variable rather than a compile-time constant.

 extern size_t size; struct sfoo; #include <stddef.h> int main(void) { unsigned char _Alignas (max_align_t) cptr[size]; // or unsigned char _Alignas (_Complex long double) cptr[size]; // some widest type struct sfoo *sfooptr = (struct sfoo *) cptr; 

If VLAs are not desired / available, declare the size as a constant, for example #define foo_N 100 , which at least should be at least necessary.

+3
source share

The bar function invokes undefined behavior: the structure pointed to by foo is not initialized.

If you are going to hide structure details, specify foo_create() , which selects one and initializes it, and foo_finalize , which frees up any resources and frees it up.

What you offer can be done to work, but is error prone and not a general solution.

+2
source share

All Articles