C Variadic Macro简化了对fprintf的调用

时间:2017-06-06 20:35:43

标签: c coding-style c-preprocessor idioms variadic-macros

我已经定义了一个笨重的宏来减少在具有大量独特日志记录情况的项目中出错的可能性......

#define BANG(...) {fprintf(stderr, "in %s(), ", __func__);\
                   fprintf(stderr, ##__VA_ARGS__);}

我可以这样成功地称之为......

BANG("Something went wrong\n");        

但以下(显然)以可怕的方式打破......

if(emulatorExitCode == 1)
    BANG("emulatorExitCode: %d (an error)\n", emulatorExitCode);        
else
    everythingIsWonderful = 1;

我当然知道原因,这是我在BANG()调用结束时不小心留下的分号;

流氓分号导致if / else构造分成两个片段,彼此分离。这是编译器错误...

main.c:74:3: error: ‘else’ without a previous ‘if’

到目前为止,解决方法是在我的编译器参数中使用-Wall -Werror -Wextra -Wpedantic,这样我就不会意外地造成我的逻辑混乱。

只要我总是在BANG()宏调用结束时省略分号,我就可以了,因为宏定义在两个fprintf();调用周围使用大括号。但是我担心以后维护我的代码的其他人不会意识到这是一个问题(它真的不明显)并且弄得一团糟。

问题

是否可以重写此宏#define以减少有问题的分号所带来的危险 OR 是否可以将其重写为将这两个调用fprintf转换为单个调用?后者因为它的可变参数和具有着名的头颅printf - 家族语义来处理而变得复杂。

1 个答案:

答案 0 :(得分:3)

多语句应包含在TO_CHAR(CAST(CAST(source_dt AS TIMESTAMP) AS TIMESTAMP WITH TIME ZONE )) AS LOCAL_DATE块中,以避免出现此类问题。

do..while

因此,您的#define BANG(...) do{ \ fprintf(stderr, "in %s(), ", __func__);\ fprintf(stderr, ##__VA_ARGS__);\ } while (0) 块会扩展为:

if

在这种情况下,使用可变参数宏的事实并不重要。