C. Support private objects in functions

Можно ли добиться поддержки приватности в структурном программировании на C? Javascript может поддерживать приватность за счет техники замыкания, C, конечно, такой возможности не имеет, но можно воспользоваться статическими объектами (с точки зрения класса памяти). Ниже приведен один из подходов

#include <stdio.h>

// init counter action
void init(int *cnt) {
  *cnt = 0;
}

// increment counter action
void increment(int *cnt) {
  (*cnt)++; 
}

// decrement counter action
void decrement(int *cnt) {
  (*cnt)--;
}

// show counter action
void show(const int *cnt) {
  printf("counter = %d\n", *cnt);
}

// counter encapsulation
void counter(void (*action) (int*)) {
  static int cnt = 0; // private
  action(&cnt);
}

int main() {
  
  counter(init);            // counter = 0;
  counter(show);         // counter = 0;
  counter(increment); // counter = 1;
  counter(increment); // counter = 2;
  counter(show);         // counter = 2;

  return 0;
}

В данном случае функции определяют возможные действия над приватным счетчиком, другие действия, как и прямое обращение к значению счетчика (статическая переменная cnt), недопустимы. Можно усложнить данную реализацию для повышения функционала действий над приватным счетчиком. Вот одна из реализаций

#include <stdio.h>
#include <string.h>
#include <stdarg.h>

// check requested init action
int is_init(const char *action) {
  return !strcmp(action, "init");
}

// check requested increment action 
int is_increment(const char *action) {
  return !strcmp(action, "increment");
}

// check requested decrement action
int is_decrement(const char *action) {
  return !strcmp(action, "decrement");


// check requested show action 
int is_show(const char *action) {
  return !strcmp(action, "show");
}

// init counter action
void init(int *cnt) {
  *cnt = 0;
}

// increment counter action
void increment(int *cnt, int n) {
  (*cnt) += n;
}

// decrement counter action
void decrement(int *cnt, int n) {
  (*cnt) -= n;
}

// show counter action
void show(const int *cnt) {
  printf("counter = %d\n", *cnt);
}

// counter encapsulation
void counter(char *action, ...) {
  static int cnt = 0;// private

  va_list par;
  va_start(par, action);
  int n = *((int *) par);// get argument value
  *((int *) par) = 0;// clear argument value
  va_end(par);

  n = n > 1 ? n : 1;

  #ifdef DEBUGMODE
printf("debug: action = %s, counter = %d, n = %d\n", action, cnt, n);
  #endif

  if (is_init(action))
    init(&cnt);
  else if (is_increment(action))
    increment(&cnt, n); 
  else if (is_decrement(action))
    decrement(&cnt, n);
  else if (is_show(action))
    show(&cnt);
  else
    printf("unsupported action\n");
}

int main() {

  counter("init");                 // counter = 0
  counter("increment");    // counter = 1
  counter("increment");    // counter = 2
  counter("show");              // counter = 2
  counter("increment", 5); // counter = 7
  counter("show");               // counter = 7
  counter("decrement");     // counter = 6
  counter("show");               // counter = 6
  counter("decrement", 3); // counter = 3
  counter("show");               // counter = 3
  counter("init");                  // counter = 0
  counter("show");               // counter = 0
  counter("test");                  // unsupported action

  return 0;
}

Или так

#include <stdio.h>
#include <stdarg.h>

// actions
typedef enum {init, increment, decrement, show, test} actions;

// check requested init action
int is_init(actions action) {
  return action == init;
}

// check requested increment action 
int is_increment(actions action) {
  return action == increment;
}

// check requested decrement action
int is_decrement(actions action) {
  return action == decrement;


// check requested show action 
int is_show(actions action) {
  return action == show;
}

// init counter action
void init_action(int *cnt) {
  *cnt = 0;
}

// increment counter action
void increment_action(int *cnt, int n) {
  (*cnt) += n;
}

// decrement counter action
void decrement_action(int *cnt, int n) {
  (*cnt) -= n;
}

// show counter action
void show_action(const int *cnt) {
  printf("counter = %d\n", *cnt);
}

// counter encapsulation
void counter(actions action, ...) {
  static int cnt = 0; // private

  va_list par;
  va_start(par, action);
  int n = *((int *) par);// get argument value
  *((int *) par) = 0;// clear argument value
  va_end(par);

  n = n > 1 ? n : 1;

  #ifdef DEBUGMODE
  printf("debug: action = %s, counter = %d, n = %d\n", action, cnt, n);
  #endif

  if (is_init(action))
    init_action(&cnt);
  else if (is_increment(action))
    increment_action(&cnt, n); 
  else if (is_decrement(action))
    decrement_action(&cnt, n);
  else if (is_show(action))
    show_action(&cnt);
  else
    printf("unsupported action\n");
}

int main() {

  counter(init);                  // counter = 0
  counter(increment);     // counter = 1
  counter(increment);     // counter = 2
  counter(show);               // counter = 2
  counter(increment, 5); // counter = 7
  counter(show);               // counter = 7
  counter(decrement);     // counter = 6
  counter(show);               // counter = 6
  counter(decrement, 3); // counter = 3
  counter(show);                // counter = 3
  counter(init);                   // counter = 0
  counter(show);                // counter = 0
  counter(test);                   // unsupported action

  return 0;
}