1

I want to force that a certain struct never gets it's fields accessed directly, always using the struct functions.

Example:

struct NoOutsideAccess { int field1;}
struct example {NoOutsideAccess f1;}

NoOutsideAccess noa;
example * ex;

&noa          // OK
&ex->noa      // OK
noa.field1;   // ERROR
ex->f1.field1 // ERROR

I've looked at C parsers and analysis tools but I'm not sure that I can do this with them.

I don't want to change the struct since it's fields will be used directly within other modules. In this case I want some script that would point out where it's being used, so that the modules that aren't supposed to can change it.

But I did found a duplicate, not sure that will match every usage but will give it a shot.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
rnunes
  • 2,785
  • 7
  • 28
  • 56
  • Have you looked at how the `FILE` structure works? The user can call functions such as `fopen()`, `fwrite()`and `fclose()` but cannot directly access the structure members. Only the address of the structure is known to the user, not its definition. – Tim Randall Aug 23 '18 at 16:23
  • 1
    Hmm... What if you didn't define the struct in any header files so it is only known to the source file that contains the accessors? Then in other source-files, instead of `struct NoOutsideAccess *`, you deal with `void *`. Hopefully someone else can chime in if this strategy is feasible or if it invokes undefined behavior. – Christian Gibbons Aug 23 '18 at 16:23
  • use `static` keyword to declare the variable. It can now only be accessed by functions in the module. Provide functions to get/set thevariable. – Paul Ogilvie Aug 23 '18 at 16:23

1 Answers1

5

One way of create opaque objects in C is to hide the definition in a C-file and only export accessor prototypes along with a forward declaration of the object in the header file:

/* foo.h */

struct foo; /* forward declaration */

struct foo *foo_new (int bar, const char *baz);
void        foo_free(struct foo *foo);

int         foo_get_bar(struct foo *foo);
const char *foo_get_baz(struct foo *foo);

Then the implementation:

/* foo.c */

struct foo {
    int bar;
    const char *baz;
};

/* implementations of foo_{new,free,get_bar,get_baz} */

NOTE: Since outside code won't know the size of struct foo, you can only work with pointers to foos there (that's where foo_new comes in).

wkz
  • 2,203
  • 1
  • 15
  • 21