Can I use getters and setters in pure C instead of using extern variables?

0

3 Answers

First of all, don't listen to anyone saying "there is no object-orientation in language x" because they have truly not understood that OO is a program design method, completely apart from language syntax.

Some languages have elegant ways to implement OO, some have not. Yet it is possible to write an object-oriented program in any language, for example in C. Similarly, your program will not automagically get a proper OO design just because you wrote it in Java, or because you used certain language keywords.

The way you implement private encapsulation in C is a bit more crude than in languages with OO support, but it does like this:

// module.h

void set_x (int n); int get_x (void); 

// module.c

static int x; // private variable void set_x (int n) { x = n; } int get_x (void) { return x; } 

// main.c

#include "module.h" int main (void) { set_x(5); printf("%d", get_x()); } 

Can call it "class" or "ADT" or "code module" as you prefer.

This is how every reasonable C program out there is written. And has been written for the past 30-40 years or so, as long as program design has existed. If you say there are no setters/getters in a C program, then that is because you have no experience of using C.

7

Yes, it's very much possible and sometimes even useful. C supports opaque types:

struct Context; 

C code compiled with only this declaration in scope can not access any hypothetical members of the struct, and can't use value of type Context either. But it can still handle pointers to Context values, so functions like these are possible:

Context *make_context(...); int context_get_foo(Context *); void context_set_foo(Context *, int); 

This pattern insulates the client C code from any changes to the size or internal layout of Context. Note that this is a stronger guarantee than simply declaring but not documenting the members: Even if the programmers duly ignore the undocumented members, by-value use of the struct is permitted (and will certainly slip in), and now the code has to be recompiled when the size changes. In other words, opaque types only handled through pointers give greater ABI stability.

6

Another approach is by using a global variable and inline functions:

// module.h

inline void set_x (int n) {extern int x; x = n;} inline int get_x (void) {extern int x; return x;} 

// module.c

int x; // global variable 

// main.c

#include "module.h" int main (void) { set_x(5); printf("%d", get_x()); } 

It has two advantages:

  1. Getters and setters become easily inlineable

  2. It becomes clear to the compiler that getters have no side effects, which allows further optimizations and produces no warnings in cases like this one:

// warning: compound statement with side effects

if(get_x() || get_y()) 

Of course, a "dedicated" (read: dumb) programmer can always write extern int x; in their code and use the variable directly. On the other hand, a "dedicated" programmer can also easily remove the static keyword and use it anyway...

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy