【问题标题】:g++ __FUNCTION__ replace timeg++ __FUNCTION__ 替换时间
【发布时间】:2011-03-13 22:00:20
【问题描述】:

谁能告诉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 行不正确。

有什么方法可以强制将字符串替换到更早的步骤以使该行正确?

__FUNCTION__ 真的被字符串替换了吗?还是编译后代码中的变量?

【问题讨论】:

    标签: c++ string compiler-construction g++ c-preprocessor


    【解决方案1】:

    您使用__FUNCTION__ 就像一个预处理器宏,但它是一个变量(请阅读http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html)。

    尝试printf("%s", __FUNCTION__) 仅用于测试,它会打印函数名称。

    【讨论】:

      【解决方案2】:

      __FUNCTION__ 不是标准的。使用__func__。正如documentation 所说,就好像:

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

      【讨论】:

        【解决方案3】:

        在 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__);完成

        【讨论】:

          【解决方案4】:

          有什么方法可以强制将字符串替换到更早的步骤以使该行正确?

          没有。 __FUNCTION__(及其标准化对应物__func__)是编译器结构。另一方面,__FILE____LINE__预处理器 结构。没有办法使__FUNCTION__ 成为预处理器构造,因为预处理器不了解 C++ 语言。当一个源文件被预处理时,预处理器完全不知道它正在查看哪个函数,因为它甚至没有函数的概念。

          另一方面,预处理器确实知道它正在处理哪个文件,它也知道它正在查看文件的哪一行,因此它能够处理__FILE____LINE__.

          这就是为什么 __func__ 被定义为等同于静态局部变量(即 编译器 构造);只有编译器才能提供此功能。

          【讨论】:

            【解决方案5】:

            这是你想要的吗?

            #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 来确保其类型安全。

            【讨论】:

            • 不幸的是,这不允许像 DBG_WHEREAMI("Error code %d", errorCode) 这样的东西。它也不能工作(至少不能移植),因为 C++(还)没有可变参数宏。
            • 不完全...我想知道我是否可以在编译时生成一个包含 func 的字符串,这样它就是运行时常量。这似乎是不可能的。
            • @bbb:是static const,运行时生成的几率为零。
            【解决方案6】:
            printf("%s" __FILE__ __LINE__ "\n", __FUNCTION__);
            

            是的,我知道那不一样。

            【讨论】:

              【解决方案7】:

              请注意,如果您创建一个类,您可以根据需要从任意数量的类型构建消息,这意味着您具有与

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-05-12
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多