Могу ли я заменить __func__ на имя идентификатора в макросе C? - PullRequest
2 голосов
/ 12 октября 2009

Я хотел бы написать макрос C, который принимает это:

int foo() {
  MY_MACRO
}

и расширяет это до:

int foo() {
  _macro_var_foo++;
}

Я обнаружил, что не могу использовать __func__, потому что это на самом деле не раскрывается в макросе; он обрабатывается препроцессором как переменная.

Есть ли способ заставить это работать?

Ответы [ 4 ]

3 голосов
/ 12 октября 2009

В стандарте C99 для __func__ указана специальная новая категория «предопределенный идентификатор» (в разделе 6.4.2.2 «Предопределенные идентификаторы»):

Идентификатор __func__ должен быть неявно объявлен переводчиком, как если бы сразу после открывающей скобки каждого определения функции, объявление

    static const char __func__[] = "function-name";

появилось, где function-name - имя лексически заключающей в себя функции

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


Руководство GCC (4.4.1) говорит в разделе 5.43 (Имена функций в виде строк):

Эти идентификаторы [означающие __func__, __FUNCTION__ и __PRETTY_FUNCTION__] не являются макросами препроцессора. В GCC 3.3 и ранее, только в C, __FUNCTION__ и __PRETTY_FUNCTION__ обрабатывались как строковые литералы; они могут быть использованы инициализировать массивы символов, и они могут быть объединены с другими строковыми литералами. НКУ 3.4 и позже относитесь к ним как к переменным, как __func__. В C ++ __FUNCTION__ и __PRETTY_FUNCTION__ всегда были переменными.

Если бы был способ аккуратно получить имя функции в препроцессоре, то вполне вероятно, что здесь приведена перекрестная ссылка на документацию, если бы она не определяла его.

3 голосов
/ 12 октября 2009

Препроцессор не знает о функциях, только исходные файлы и номера строк. На этом этапе он не выполняет синтаксический анализ, просто текстовый анализ и замены. Вот почему __func__ является магической переменной, а не магическим макросом, таким как __FILE__ и __LINE__.

1 голос
/ 12 октября 2009

Технически, ответ на ваш вопрос "да", есть "какой-то путь". Но я думаю, что вы уже знали это, и это правда, что вы не можете иметь дело с этим на уровне макропроцессора.

Конечно, всегда есть способ, просто вам может понадобиться очень длинная лента на этой машине Тьюринга.

Я думаю, что вы уже знаете это, но для записи вы можете получить желаемый общий результат:

#define MY_MACRO f_dictionary(__func__, ADDONE);

Так что теперь вам просто нужно реализовать f_dictionary и опцию ADDONE для него.

1 голос
/ 12 октября 2009

Это можно сделать с помощью объединения токенов .

#define MY_MACRO(baz) _macro_var_##baz++;

#define FUNC_WRAPPER(bar)\
int bar()\
{\
    MY_MACRO(bar)\
}

FUNC_WRAPPER(foo)

Выходные данные gcc -E :

int foo(){ _macro_var_foo++;}

Версия, имеющая дело со списками аргументов с использованием переменных макросов и макросов x:

#define MY_MACRO(baz) _macro_var_##baz++;

#define FUNC_DEF(ret_type,bar,...)\
ret_type bar(__VA_ARGS__)\
{\
    MY_MACRO(bar)\
    FUNC_CONTENTS\
}

#define FUNC_CONTENTS\
    printf("Do some stuff\n", s1, s2);
FUNC_DEF(int, foo, char *s1, char *s2)
#undef FUNC_CONTENT
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...