Возможно ли сделать аналог синглтона майерса в си?

Я не хочу делать глобальную переменную, потому что она доставляет массу неудобство с дебагом. Могу ли я сделать что то похожее на синглтон майерса?

static char* init(){
   static char* test = malloc(30);
   return test;
}

Компилятор выдает следующую ошибку

Initializer element is not a compile-time constant


Ответы (4 шт):

Автор решения: Mikhailo
char* init() {
    static char* test = NULL;
    if (test == NULL) test = malloc(30);
    return test;
    }
→ Ссылка
Автор решения: AlexGlebe

Лисп язык (LISP) подсказал идею : функцию init сделать указателем на функцию. Сначала она будет указывать на инициализацию, а дальше просто возвращать значение. Но этот указатель никто не защищает. Если его не трогать будет всё работать.

singlet.h

// тип функции
typedef char * (  * singleton_functype ) ( void )  ;
// указатель на неё
extern  singleton_functype  init ;

singletmain.c

// gcc -Wall -Wextra -Wpedantic -Winline -Wshadow -Wconversion -std=c11 -Os singlet.c  singletmain.c -o singlet
# include <stdio.h>
# include "singlet.h"

int main(){
  puts("main:begin");
  char * st = init ( ) ;
  * st = '\00' ;
  puts("main:next");
  init ( ) ;
  puts("main:end");
}

singlet.c

# include <stdio.h>
# include <stdlib.h>
# include "singlet.h"

// указатель виден только внутри данного файла
static  char  * test ;

// возвращаем уже готовый указатель
char * singleton_work ( void ) {
  puts("singleton_work");
  return  test  ;
}

// выделяем память И меняем указатель рабочей функции
char * singleton_init ( void ) {
  puts("singleton_init");
  test  = malloc  ( 30  ) ;
  init = singleton_work  ;
  return  test  ;
}

// сначала указываем на функцию с выделением памяти
singleton_functype  init = singleton_init  ;

проверяем :

> ./singlet 
main:begin
singleton_init
main:next
singleton_work
main:end
→ Ссылка
Автор решения: Qwertiy
char *init(){
  static char test[30];
  return test;
}
→ Ссылка
Автор решения: user7860670

Синглетон (без следов Майерса): не занимается созданием или уничтожением экземпляра, только разделяет владением им и предоставляет к нему доступ:

static char * s_p_instance = NULL;

void instance_set(char * p_instance)
{
   assert(! s_p_instance);
   s_p_instance = p_instance;
   assert(s_p_instance);
   return;
}

void instance_reset(void)
{
   s_p_instance = NULL;
   return;
}

char * instance_fetch(void)
{
   assert(s_p_instance);
   return s_p_instance ;
}

Использование:

int main()
{
    char * p_instance = (char *) calloc(30, 1);
    instance_set(p_instance);
    ...
    puts(instance_fetch());
    ...
    instance_reset();
    free(p_instance);
}

→ Ссылка