C Ошибка компиляции, если функция инициализации не была вызвана - PullRequest
0 голосов
/ 25 июня 2019

Я хотел бы создать что-то вроде класса в C и уведомить разработчика, если «класс» не был инициализирован перед использованием его функций. Это легко сделать во время выполнения кода, но было бы лучше во время компиляции.

Если я вызову get_something () до init (), я бы хотел сбросить ошибку во время компиляции. Является ли это возможным?

//something.c
void init() {...}

int get_something() {...}

//main.c
int main()
{
#include something.h

get_something(); //pls drop compile error because wasn't initialized
return 0;
}

Ответы [ 2 ]

3 голосов
/ 25 июня 2019

В общем случае это не выполнимо во время компиляции, так как нет способа передать такие требования, и даже если бы они были, компилятор не мог бы доказать в каждом случае, что все пути кода, ведущие к get_something сначала вызвали init.

В некоторых особых случаях вы можете получить предупреждение во время компиляции через некоторые сомнительные хаки, например, если ваш something.h содержит static void init(void) { real_init(); } - тогда некоторые компиляторыс достаточным количеством включенных предупреждений будет предупреждать о неиспользованной static функции init, если вы не вызовите ее (откуда угодно - могут быть пути кода, которые ее не вызывают).

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

1 голос
/ 25 июня 2019

AFAIK, нет никакого способа сделать это, очень уродливый трюк, если вы можете использовать статические утверждения (C11) и предопределенный макрос __COUNTER__ - это проверка, вызывается ли init() в какой-то момент в программе, что-то вроде:

#include <stdio.h>
#include <assert.h>

#define init() do {__COUNTER__; init();} while(0);

void (init)(void) // parenthesis prevents the expansion and allows you 
                  // to call a macro with the same name
{
    /* ... */
}

int get_something(void)
{
    /* ... */
    return 0;
}

int main(void)
{
    static_assert(__COUNTER__ == 1, "init() is never used");
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...