正确地字符串化和连接宏参数

时间:2018-03-07 18:26:07

标签: c macros c-preprocessor

基本上,我有以下宏定义:

#include <stdio.h>

#define altErrMsg(x,y,z) x":"#y":"z
#define errMSG(x,y,z) altErrMsg(x,y,z)
#define __failure() errMSG(__FILE__,__LINE__,__FUNCTION__)

int
main (int argc, char **argv) 
{
    puts (__failure ());
    return 0;
}

__failure()应该以{{1​​}}的形式打印一些调试信息。为此,我使用了GCC的预定义宏"filename:line:function"__LINE__, __FILE__。我使用了间接,以便在连接之前扩展预定义的宏。必须对__FUNCTION__的扩展进行字符串化(使用参数名称前的__LINE__)。

AFAIK,#将扩展为类似:“test.c”“:”“20”“:”“main”将引用一个单独的字符串常量“test.c:20:main” 。但那并没有发生,相反,我遇到了错误:

__failure()

使用test.c:5:46: error: expected ‘)’ before ‘__FUNCTION__’ #define __failure() errMSG(__FILE__,__LINE__,__FUNCTION__) ^ test.c:3:35: note: in definition of macro ‘altErrMsg’ #define altErrMsg(x,y,z) x":"#y":"z ^ test.c:5:21: note: in expansion of macro ‘errMSG’ #define __failure() errMSG(__FILE__,__LINE__,__FUNCTION__) ^~~~~~ test.c:10:11: note: in expansion of macro ‘__failure’ puts (__failure ()); 进行编译显示gcc -E永远不会展开,最终字符串如下所示:__FUNCTION__这是错误的语法但我不知道为什么会发生这种情况!

这种行为有解释吗?以及对问题的任何更正?

1 个答案:

答案 0 :(得分:1)

如果您从Predefined macros

询问原因
  

C99介绍__func__,GCC长期提供__FUNCTION__。这两个都是包含当前函数名称的字符串(存在轻微的语义差异;请参阅GCC手册)。 它们都不是宏; 预处理器不知道当前函数的名称。

不是宏 - 这就是宏扩展的原因。如果这是你的意图,它将无法工作。 (如你所见)。

解决方案是使用一个函数,您将传递这些东西并相应地打印它们。那会有用。

void my_log( const char * filename, int linenumber, const char * funcname){
    fprintf(sdtout,"%s[%d]%s\n",filename, linenumber, funcname);
}

并调用my_log(__FILE__,__LINE__,__FUNCTION__);