Получение имени вызывающей функции в C (без использования препроцессора) - PullRequest
1 голос
/ 08 августа 2010

Мне было интересно, есть ли способ найти, какая функция вызвала текущую функцию (во время выполнения) в C.

Я знаю, что вы можете использовать __FUNCTION__ в gcc, но есть ли способ без использования препроцессора C?

Вероятно, нет.

Приветствия

Ответы [ 6 ]

6 голосов
/ 29 ноября 2011

Предполагая, что у вас есть функция f (), из которой вы хотите узнать вызывающего.

Переименуйте эту функцию в f_func () и определите макрос f (), который печатает __func__, а затем вызовет f_func ().Пример:

void
f_func()
{
        do something;
}

#define f() \
        do { \
                printf("f called from %s\n", __func__); \
                f_func(); \
        } while (0)

void
a()
{
        f();
}

void
b()
{
        f();
}

int
main(int argc, char **argv)
{
        a();
        b();

        return(0);
}
6 голосов
/ 08 августа 2010

Нет, нет. C не является особенно интроспективным языком - такие вещи, как имя функции (или части вашего стека вызовов), просто недоступны во время выполнения каким-либо вменяемым образом.

Если, по какой-то причине, вы ищете много работы для очень небольшого преимущества, тогда вы можете создавать свои программы с отладочными символами, и вы можете писать обход стека и отладочный код поиска символов. Тогда вы сможете узнать это на лету. Но будьте осторожны, потому что символы, которые вы увидите в отладочной информации, будут украшены информацией о типе, если у вас есть C ++.

Вы отметили это сообщение gcc, поэтому доступны соответствующие подробности, однако это относится к категории «не рекомендуется» и «не обязательно будет одинаковой для разных версий компилятора».

2 голосов
/ 08 августа 2010

Нет способа получить имя функции во время выполнения.Единственный способ - это препроцессор, но он очень ограничен в своих возможностях.Если у вас есть отладочная информация, вы можете пройтись по стеку и получить имена функций из отладочной информации.Однако это не надежное и не переносимое решение.

1 голос
/ 19 июня 2014

NO

Короткий ответ НЕТ

но с препроцессором это можно сделать вот так

Получение имени вызывающей функции в C (с использованием препроцессора)

Предполагается, что у вас есть функция f (), из которой вы хотите знать вызывающую функцию только для целей отладки.

Переименуйте эту функцию в f_func () и определите макрос f (), который вызывает версию f, которая печатает func , а затем вызывает f_func (), когда определено DEBUG.

В финальной версии информация удаляется путем вызова реальной функции f_func ()

Пример

#ifdef DEBUG
  #define f(a,b,c) f_debug(a,b,c, __func__)
#else
  #define f(a,b,c) f_func(a,b,c)
#endif

bool f_func(int par1, int par2, int par3)
{
  do_somthing();
}

bool f_debug((int par1, int par2, int par3, const char calling_func_name[])
{
  printf("f called from %s\n", calling_func_name); 
  f_func(); 
}

void a()
{
  f();
}

void b()
{
  f();
}

int main(int argc, char **argv)
{
        a();
        b();

        return(0);
}

Результат:

когда определен DEBUG

f вызывается с
Ф звонил из б

1 голос
/ 08 августа 2010

Есть пара функций GNU , которые позволяют вам получать адреса функций и имена из обратной трассировки - backtrace() и backtrace_symbols(), но вам нужно скомпилировать ваш двоичный файл с -rdynamic flag

0 голосов
/ 08 августа 2010

Используйте идентификатор __func__. стандарт (раздел 6.4.2.2) требует, чтобы присутствовал именно для этой цели:

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

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

, где function-name - это имя лексически заключающей функции.

Как отмечает Стив Джессоп в комментарии, это не является частью препроцессора как такового, а является неотъемлемой частью компилятора.

Вполне могут быть способы узнать это имя с помощьюходить по стеку и смотреть на символы отладки.Милый, но безумный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...