функция G++ заменяет время

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

#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 неверна.

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

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

7 ответов


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

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

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

вот почему __func__ определяется как эквивалентная статической локальной переменной (т. е. a компилятор construct); только компилятор может предоставить эту функциональность.


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

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


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

<ret-type> function_name( <args> )
{
    static const char __func__[] = "function-name";
    ...

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

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


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

#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, чтобы убедиться, что это безопасно.


printf("%s" __FILE__ __LINE__ "\n", __FUNCTION__);

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


обратите внимание, что если вы создаете класс, вы можете построить сообщение из любого количества типов, как вы хотите, что означает, что у вас есть аналогичный эффект

// 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");

обратите внимание, что вы можете объявить операторы

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

зависит от того, что вы предпочитаете использовать. Мне нравится (), потому что он автоматически защищает ваши выражения. т. е. если вы хотите вывести "count

LOG_DEBUG << "found " << (count << 3) << " items";