实现格式化打印,当没有参数时可能不执行任何操作

时间:2018-11-14 10:12:55

标签: c macros printf variadic-functions

我想实现一个名为PRINT的宏,该宏将获取零个或多个参数,并执行以下操作:

  1. 如果参数为零,则不执行任何操作。
  2. 如果得到一个或多个参数-就像printf一样。

我成功实现了它,正如您在下面的代码中看到的那样,但是仅在以零为参数的情况下,以空字符串调用printf为代价。

有没有一种方法可以在不调用printf的情况下处理零参数情况(当您只想什么都不做时,打印某些内容效率不高)?

#include <stdio.h>

#define PRINT(...) printf("" __VA_ARGS__);

int main(){
    PRINT();
    PRINT("print\n");
    PRINT("print number: %d\n", 7);
    return 0;
}   

输出:

print
print number: 7  

3 个答案:

答案 0 :(得分:1)

如果gcc和clang传递了空格式字符串,则它们将完全消除对SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data 的调用。优化可能是相当普遍的。

有关在gcc.godbolt.org上的反汇编,请参见herehere

简而言之,不用担心。

答案 1 :(得分:1)

解决方案是:

x = [-2,-1,0,1,2]
y =[-2,1,0,1,2]

plt.axvline(0)
plt.axhline(0)
#plt.axis('off')

plt.scatter(x,y)

对于此原始文本:

#define Argument1(a,...)    Argument2(a
#define Argument2(a, b,...) b
#define TestEmpty()         ,
#define PRINT(...)          Argument1(TestEmpty __VA_ARGS__ (),), printf(__VA_ARGS__);,)

预处理的结果是:

Test 0: PRINT()
Test 1: PRINT("Hello, world.\n")
Test 2: PRINT("Result is %d.\n", result)
Test 3: PRINT("%d = %g.\n", 3, 3.)

这要求Test 0: Test 1: printf("Hello, world.\n"); Test 2: printf("Result is %d.\n", result); Test 3: printf("%d = %g.\n", 3, 3.); 的参数不能以括号括起来,对于这个特定问题来说似乎可以接受。此处的代码不是在可能出现括号时检测空参数的通用解决方案。

说明:

  • 在准备替换PRINT时,替换了PRINT__VA_ARGS__目前未替换,因为它后面没有括号。
  • 然后替换TestEmpty,并重新扫描结果。
  • 已标识
  • PRINT可以替换。为此,将处理其参数。
  • 这时,如果Argument1为空,则有令牌__VA_ARGS__,它们被TestEmpty ()取代。否则,将保留,。请注意,如果存在TestEmpty <some tokens> (),则TestEmpty ()会扩展为,的第一个参数。它不是参数分隔符,因为Argument1的参数已经确定。
  • 然后替换Argument1,生成Argument1(如果Argument2(,为空)或__VA_ARGS,并可能后面加上其他标记(否则)。
  • 根据Argument2(TestEmpty是否为空,结果为Argument2(,, printf();,)Argument2(TestEmpty <some tokens>, printf(<some tokens>);,)
  • 现在重新扫描了令牌以进行进一步替换,因此__VA_ARGS__现在将被识别为参数分隔符。
  • 最后,,被替换为空令牌列表或Argument2

答案 2 :(得分:0)

如果您确实要将空参数列表的检查工作外包给宏,则可能是这样的:

#define HAS_ARGS(...) (sizeof( (char[]){#__VA_ARGS__} ) > 1)

#define PRINT(...) (HAS_ARGS(__VA_ARGS__) ? printf("" __VA_ARGS__) : (void)0)

仅当空字符串=空终止符时,这取决于复合文字的大小为1。示例:

#include <stdio.h>

#define HAS_ARGS(...) (sizeof( (char[]){#__VA_ARGS__} ) > 1)

#define PRINT(...) (HAS_ARGS(__VA_ARGS__) ? printf("" __VA_ARGS__) : (void)0)

int main (void)
{
  int i = 5;
  PRINT("%d\n", i);
  PRINT();
}