функция 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, чтобы убедиться, что это безопасно.
обратите внимание, что если вы создаете класс, вы можете построить сообщение из любого количества типов, как вы хотите, что означает, что у вас есть аналогичный эффект
// 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";