g ++ __FUNCTION__ заменить время - PullRequest
8 голосов
/ 09 июля 2010

Может кто-нибудь сказать, когда g ++ заменяет макрос __FUNCTION__ на строку, содержащую имя функции?Кажется, он не может заменить его, пока не проверит синтаксическую правильность исходного кода, то есть следующее не будет работать

#include <whatsneeded>
#define DBG_WHEREAMI __FUNCTION__ __FILE__ __LINE__

int main(int argc, char* argv)
{
  printf(DBG_WHEREAMI "\n"); //*
}

, так как после предварительной обработки с использованием

g++ -E test.cc

источник выглядиткак

[...]

int main(int argc, char* argv)
{
  printf(__FUNCTION__ "test.cc" "6" "\n"); //*
}

, и теперь компилятор правильно выдает, потому что строка * ed неверна.

Есть ли способ заставить эту замену строкой перейти на более ранний шаг, чтобы строкаправильно?

Действительно ли __FUNCTION__ действительно заменяется строкой?Или это переменная в скомпилированном коде?

Ответы [ 7 ]

15 голосов
/ 09 июля 2010

Есть ли способ заставить эту замену строкой перейти на более ранний шаг, чтобы строка была правильной?

Нет.__FUNCTION__ (и его стандартизированный аналог __func__) являются компиляторами конструкций.__FILE__ и __LINE__, с другой стороны, являются конструкциями препроцессора .Невозможно сделать __FUNCTION__ конструкцией препроцессора, поскольку препроцессор не знает языка C ++.Когда исходный файл подвергается предварительной обработке, препроцессор абсолютно не знает, на какую функцию он смотрит, потому что у него даже нет понятия функций.

С другой стороны,препроцессор знает , над каким файлом он работает, и также знает, какую строку файла он просматривает, поэтому он может обрабатывать __FILE__ и __LINE__.

* 1023.* Вот почему __func__ определяется как эквивалент статической локальной переменной (т. Е. Конструкция compiler );только компилятор может обеспечить эту функциональность.
3 голосов
/ 09 июля 2010

Вы используете __FUNCTION__ как макрос препроцессора, но это переменная (пожалуйста, прочитайте http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html).

Попробуйте printf("%s", __FUNCTION__) только для тестирования, и он напечатает имя функции.

2 голосов
/ 09 июля 2010

В C / C ++ препроцессор превратит "my " "name " "is " "Bob" в строковый литерал "my name is Bob"; поскольку __FILE__ и __LINE__ являются инструкциями препроцессора, "We are on line " __LINE__ передаст компилятору сообщение "Мы на линии 27".

__FUNCTION__ обычно является синонимом __func__. __func__ можно рассматривать как псевдофункцию, которая возвращает имя функции, в которой она вызывается. Это может сделать только компилятор, а не препроцессор. Поскольку __func__ не оценивается препроцессором, вы не получаете автоматическую конкатенацию. Так что если вы используете printf, это должно быть сделано printf("the function name is %s", __func__);

2 голосов
/ 09 июля 2010

__FUNCTION__ не стандартно.Используйте __func__.Как говорится в документации , это выглядит так:

<ret-type> function_name( <args> )
{
    static const char __func__[] = "function-name";
    ...
1 голос
/ 09 июля 2010

Это то, что вы хотите?

#include <stdio.h>

#define DBG_WHEREAMI(X) printf("%s %s(%d): %s\n",__func__,__FILE__,__LINE__,X)

int main(int argc, char* argv)
{
  DBG_WHEREAMI("Starting");
}

Примечание. Поскольку вы пометили это как C ++, вам, вероятно, следует использовать iostreams, чтобы убедиться, что он безопасен для типов.

0 голосов
/ 02 февраля 2013

Обратите внимание, что если вы создаете класс, вы можете создавать сообщения из любого числа типов по своему усмотрению, что означает, что вы получаете эффект, аналогичный оператору << или формату в printf (3C).Примерно так: </p>

// make sure log remains copyable
class log
{
public:
  log(const char *function, const char *filename, int line)
  {
    f_message << function << ":" << filename << ":" << line << ": ";
  }
  ~log()
  {
    //printf("%s\n", f_message.str().c_str()); -- printf?!
    std::cerr << f_message.str() << std::endl;
  }

  log& operator () (const char *value)
  {
    f_message << value;
  }
  log& operator () (int value)
  {
    f_message << value;
  }
  // repeat with all the types you want to support in the base class
  // (should be all the basic types at least)
private:
  sstream f_message;
};

// start the magic here
log log_error(const char *func, const char *file, int line)
{
  log l(func, file, line);
  return l;
}

// NOTE: No ';' at the end here!
#define LOG_DEBUG  log_error(__func__, __FILE__, __LINE__)

// usage sample:
LOG_DEBUG("found ")(count)(" items");

Обратите внимание, что вы можете объявлять операторы << вместо ().В этом случае итоговое использование будет примерно таким: </p>

LOG_DEBUG << "found " << count << " items";

Зависит от того, что вы предпочитаете использовать.Я вроде как (), потому что он защищает ваши выражения автоматически.то есть, если вы хотите вывести «count << 3», вам нужно написать: </p>

LOG_DEBUG << "found " << (count << 3) << " items";
0 голосов
/ 10 июля 2010
printf("%s" __FILE__ __LINE__ "\n", __FUNCTION__);

Да, я знаю, что это не совсем то же самое.

...