Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

In my opinion, hiding the definition of a structure in C generally makes code safer, as you enforce—with the help of the compiler—that no member of the structure can be accessed directly.

However, it has a downside in that a user of the structure cannot declare variables of its type to be put on the stack, because the size of the structure becomes unavailable this way (and, therefore, the user has to resort to allocating on the heap via malloc() even when it is undesirable).

This can be (partially) solved via the alloca(3) function that is present in all major libc implementations, even though it does not conform to POSIX.

Keeping these pros and cons in mind, can such design be considered good in general?

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);
}
like image 891
Alexander Solovets Avatar asked Dec 15 '15 22:12

Alexander Solovets


People also ask

Can we make structure members Private C?

The answer is "Yes! In C++, we can declare private members in the structure". So the important thing is that "we can declare a structure just like a class with private and public members".

Are structs private in C?

In the C++ language, a struct is identical to a C++ class but has a different default visibility: class members are private by default, whereas struct members are public by default.


1 Answers

Yes, it is a good practice to hide data.

As an alternate to the alloca(foo_size); pattern, one can declare an aligned character array and perform a pointer conversion. The pointer conversion is not fully portable, though. The character array needs to be a VLA, if the size is defined by a variable and not 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 or available, declare the size as a constant (#define foo_N 100) that is guaranteed to be at least as much as needed.

like image 138
chux - Reinstate Monica Avatar answered Oct 02 '22 18:10

chux - Reinstate Monica