C Private Variables Get and Set methods

You can type:

static int c;

This way, the ".o" won't export the "c" variable.


If you want private variables in c, there are a number of techniques that can approximate a private variable, but the C language actually doesn't have a "protection" concept that extends to private, public, protected (as C++ does).

C will show the name of any variable (it's a requirement in C) so you must approach it with the idea of information hiding the type of the variable (making dereferencing quite difficult).

One trick is to define the variable as an void* with the actual variable type being known in only one .c module.

 /* somefile.h */

 extern void* counter; 

 /* somefile.c */

 #include "somefile.h"

 int actualCounter = 0;
 void* counter = &actualCounter;

 /* otherfile.c */

 #include "somefile.h"

 // we can see "counter", but we cannot "use" it here; because we don't have access
 // to the real "hidden" type of "int".

A better method is to extend this idea using the struct keyword, and make pseudo-methods, like so

 /* person.h */

 struct s_person;

 typedef Person struct s_person;

 Person* new_Person(char* name);
 void delete_Person(Person* person);

 void Person_setName(Person* person, char* name);
 char* Person_getName(Person* person);

 /* person.c */

 struct s_person {
   char* name;
 };

 Person* new_Person(char* name) {
   Person* object = (Person*)malloc(sizeof(struct s_person));
   // duplicate the string for more security, otherwise constructor
   // could manipulate the "private" string after construction.
   object->name = strdup(name);
   return object;
 }

 void delete_Person(Person* person) {
   // some implementations pass a Person** to set the reference to 0
   // this implementation requires that the caller sets his own references to 0
   free(person->name);
   free(person);
 }

 void Person_setName(Person* person, char* name) {
   // free the old
   free(person->name);
   // duplicate the new to provide "out of simulated class" modification by malicious 
   // name setter.
   person->name = strdup(name);
 }

 char* Person_getName(Person* person) {
   // must return a copy, otherwise one can manipulate name
   // from reference provided by Person_getName(...);
   return strdup(person->name);
 }

 /* otherfile.c */

 #include "Person.h"

 /* Now we can hold Person "simulated objects", but we cannot */
 /* manipulate their "state" without using the C simulated object */
 /* methods */

 int main(int argc, char** argv) {

   Person* bob = new_Person("bob");
   printf("%s\n", Person_getName(bob));
   delete_Person(bob);
   // critical or we hold a pointer to freed memory.
   bob =  0;

   return 0;
 }

Techniques like this have several variants, one is to have a "public struct" with a void* pointer to the "private struct". One is to include the "methods" as function pointers in the "public struct" (a step towards supporting polymorphism), one is to actually write a full and proper C++ type system which attempts to resolve things exactly as C++ would (class hierarchies, polymorphisim, late binding, information hiding, etc).

Basically, you can get some "object-oriented-ness" without too much work, but as you add more features of -ornamentation, you will add more glue code (until it is much simpler to actually use an object-oriented programming language).


You make the variable static. When a global variable is made static, its scope is restricted to the current file.

An example is as follows:

Filename: main.c

#include <stdio.h>

#include "header.h"

extern int get();
extern void set(int);

int main()
{
    set(10);
    printf("value = %d \n", get());   
    set(20);
    printf("value = %d \n", get());   
    set(30);
    printf("value = %d \n", get());   
    set(40);
    printf("value = %d \n", get());   
    return 0;
}

Filename: header.h

#include <stdio.h>

int get(void);
void set(int);

Filename: header.c

#include "header.h"

static int value = 0;

int get(void)
{
    return value;
}

void set(int new_value)
{
    value = new_value;
}

Output:

$ gcc -Wall -o main main.c header.h header.c 
$ ./main 
value = 10 
value = 20 
value = 30 
value = 40 
$