我想实现一个名为PRINT
的宏,该宏将获取零个或多个参数,并执行以下操作:
我成功实现了它,正如您在下面的代码中看到的那样,但是仅在以零为参数的情况下,以空字符串调用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
答案 0 :(得分:1)
如果gcc和clang传递了空格式字符串,则它们将完全消除对SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
的调用。优化可能是相当普遍的。
有关在gcc.godbolt.org上的反汇编,请参见here和here。
简而言之,不用担心。
答案 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();
}