2014-11-25 90 views
2

我已将libiniparser库合并到我的Android NDK应用程序中。这个库的一个问题是直接写日志到stdout/stderrC递归预处理器定义

我不想大量修改代码,所以我写了一个宏登录logcat

#include <android/log.h> 

#define LOG_TAG "libinipaser" 

#define fprintf(pipe,...) \ 
    if (pipe == stdout) \ 
     __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__); \ 
    else if (pipe == stderr) \ 
     __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__); \ 
    else \ 
     fprintf(pipe,__VA_ARGS__) 

直到最后一刻,我不知道它会工作,但它的作品。我已签预处理器输出(GCC-E),它看起来像我预想的上述

fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]); 

线预处理照顾:

if (f == (&__sF[1])) __android_log_print(ANDROID_LOG_INFO,"libinipaser","[%s]=[%s]\n", d->key[i], d->val[i]); else if (f == (&__sF[2])) __android_log_print(ANDROID_LOG_ERROR,"libinipaser","[%s]=[%s]\n", d->key[i], d->val[i]); else fprintf(f,"[%s]=[%s]\n", d->key[i], d->val[i]); 

有人能解释一下:

  1. 请问C预支持递归宏?
  2. 它是如何发生的LOG_TAG定义被替换,但内部fprintf不是?
  3. 这个定义会在任何地方工作吗?
  4. 这是一个好方法吗?
+2

这很简单,C预处理没有递归的宏。 ([Wikipedia reference。](http://en.wikipedia.org/wiki/C_preprocessor#Other_uses)) – 2014-11-25 10:02:01

回答

5
  1. 没有,C预处理不“支持”递归宏,而你的情况意味着它不正是你想要的东西,而不是扩大宏观递归(这不会永远终止)。
  2. 预处理器不会扩展先前在当前扩展中已扩展的令牌。
  3. 我这么认为。根据https://gcc.gnu.org/onlinedocs/cpp/Traditional-macros.html,此行为似乎是ISO C标准的一部分(其中“传统模式”表示在ISO C89标准之前使用的模式)。
  4. 这对我来说看起来很明智。
2

我只会回答问题4。 mstorsjo有其余的很多录音。

不,这不是一个好主意。如果有另一种“适当”的方式来实现结果,宏魔法通常是不鼓励的 - 这可能是一个常数或函数(就像这种情况一样)。

在这种情况下,看起来是fprintf(通常情况下)返回int(字符输出的计数)的调用不会计算为此。例如,int count=fprintf(file,"Hello");将是一个编译错误。

这对您来说可能不是问题,但考虑到一般情况,任何在翻译单元中包含该宏定义的任何代码的人可能已经破译了他们的代码,并且找到了找到原因的Dickens工作,那么需要#undefine这个宏让他们的代码回来!

马科斯并不差。它们在条件编译和调试中绝对占有一席之地。就我个人而言,我为了这个目的而想念他们。

但是,作为一般规则,如果有另一种语言结构来做同样的事情 - 使用它。

这里有讨论宏的优点和dismerits一些优秀的答案:

Why are preprocessor macros evil and what are the alternatives?