C递归预处理器定义

时间:2014-11-25 09:52:39

标签: c android-ndk c-preprocessor

我已将libiniparser库合并到我的Android NDK应用程序中。此库写入的一个问题是直接记录到stdout / stderr

我不想大量修改代码,所以我写了一个宏来登录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 个答案:

答案 0 :(得分:5)

  1. 不,c预处理器没有&#34;支持&#34;递归宏,在你的情况下意味着它完全符合你的要求,而不是递归地扩展宏(它不会终止)。
  2. 预处理器不会扩展先前在当前扩展中扩展的令牌。
  3. 我是这么认为的。根据{{​​3}},这种行为似乎是ISO C标准的一部分(其中&#34;传统模式&#34;表示在ISO C89标准之前使用的模式)。
  4. 这对我来说很明智。

答案 1 :(得分:2)

我只回答问题4。 mstorsjo的其余部分几乎都是录音。

没有。这不是一个好主意。宏魔术通常不鼓励在另一种“正确”的方式来实现结果 - 可能是常数或函数(如本例所示)。

在这种情况下,似乎是对fprintf的调用(通常)返回int(字符输出的数量)将不会评估。例如,int count=fprintf(file,"Hello");将是编译错误。

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

马科斯并不差。它们肯定在条件编译和调试中占有一席之地。我个人在Java中为此目的而想念他们。

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

在这里讨论宏的优点和缺点有一些很好的答案:

Why are preprocessor macros evil and what are the alternatives?