是否可以使功能静音?例如:
#include <stdio.h>
int function(){
printf("BLAH!");
return 10;
}
int main(){
printf("%d", silence( function()) );
return 0;
}
而不是:
BLAH!
10
我会得到:
10
是否可以?如果阳性怎么办?
几乎可以完成您想要的操作的一种非常复杂的方法是使用dup2()系统调用。这需要在调用fflush(stdout); dup2(silentfd, stdout);
之前执行,然后再复制回来: . 所以不可能像 just 那样做,因为这个结构只允许在已经执行后执行代码。function()
fflush(stdout); dup2(savedstdoutfd, stdout);
silence(function())
function()
文件描述符silentfd
和savedstdoutfd
必须提前准备好(未经测试的代码):
int silentfd = open("/dev/null",O_WRONLY);
int savedstdoutfd = dup(stdout);
这几乎肯定不是您真正想要的,但只要您的问题被表述为“可能吗?”,答案就是“几乎”。
使用宏功能和空设备。
例如对于窗户
#include <stdio.h>
#define silence(x) (_stream = freopen("NUL:", "w", stdout), _ret_value = x,_stream = freopen("CON:", "w", stdout),_ret_value)
int _ret_value;
FILE *_stream;
int function(){
printf("BLAH!");
return 10;
}
int main(void){
printf("%d", silence( function()) );
return 0;
}
不,它不可能。但是,您可以尝试将标准输出临时重定向到其他内容。这可能接近你想要的。
您可以使用此宏而不是printf
能够阻止打印:
int flag=0;
#define PRINT(...) if(flag){printf(...)}
然后通过考虑变量来使用 PRINT 宏flag
。如果flag==1
,该函数将打印,如果flag==0
,该函数将不打印。
如果您正在设计该功能,请执行以下操作:
int function(void (*printer)(char *)){
if (!printer)
printer = printf;
printer("BLAH!");
return 10;
}
void silence(char *s){
return;
}
int main(int argc, char **argv){
printf("%d\n", function(silence));
return 0;
}
那应该做你正在寻找的东西。不幸的是,我没有测试它,我的 C 可能有点生锈了。
当然,如果function
不是您可以控制的,那么已经发布的答案都是正确的解决方案。
实际上,如果您自己设计函数,只需执行以下操作:
int function(int print){
if (print)
printf("BLAH!");
return 10;
}
function(0); /* Won't print anything */
function(!0); /* Will print "BLAH!" */
因为0
是假的,任何非零(或!0
)值都是真。我的上述建议很容易出错,因为您必须能够模仿您希望使用的任何其他功能的printf
签名。silence
使用GCC 扩展,您可能会考虑使用类似的宏
bool silent;
#define silence(X) ({int _x; quiet(); _x = (X); verbose(); _x; })
#define printf(Fmt,...) \
do{if (!silent) printf(Fmt,##__VA_ARGS__);}while(0)
只有当它的参数是一个表达式(或使用typeof )时,该silence
宏才会起作用我还假设从未使用过的结果。回想一下,“递归”宏是经过特殊预处理的,(在那个宏中)的内部出现是逐字保留的,没有宏扩展。X
int
printf
printf
printf
请注意 thatsilence
不能是一个函数(否则,它的参数将在调用它之前进行评估)。并且您需要 GCC语句表达式扩展来“记住”某个变量中参数的结果_x
(您可以使用和预处理器连接生成该名称__COUNTER__
),将其作为silence
宏调用的值返回。
然后你需要定义你的函数quiet()
,verbose()
也许像
void quiet()
{
silent = true;
}
void verbose()
{
silent = false,
}
如果您不想定义printf
为您的宏,您可以使用freopen(3) on stdout
(可能与"/dev/null"
etc...)或执行dup2(2)技巧(如Pascal Cuoq 建议的)。
如果您的代码库很大,并且您想要更严肃的事情并且愿意花费数天或数周的工作,请考虑使用插件或MELT扩展定制您的 GCC 编译器(或请别人来做)。请注意,printf
GCC 知道这一点。
实际上,您应该定义自己的宏,例如
#define myprintf(Fmt, ...) do{if (!silent) \
printf(Fmt,__VA_ARGS__);}while(0)
并且只是使用myprintf
而不是printf
到处使用,这是一个便携的技巧。当然,我假设您没有printf
作为函数指针传递。
对于调试,我实际上建议
#define dbgprintf(Fmt,...) do{if (wantdebug) \
printf("%s:%d:" Fmt "\n", __FILE__, __LINE__, \
##__VA_ARGS__);}while(0)
然后我在我的代码中使用dbgprintf("i=%d",i)
或简单地使用。dbgprintf("foo here")
我使用##__VA_ARGS__
的是 GCC 扩展,不接受可变参数宏的可变参数。如果您想要严格的 C99,您只会说__VA_ARGS__
,并且每个dbgprintf
格式都需要一个参数。
您也可以重新实现自己的printf
功能,但我不建议这样做。
(请注意,事情可能更复杂,您可以使用fputs
not printf
.... 进行打印。)
不幸的是,如果您有明确打印的函数并像这样调用它,那么它将始终打印。如果您想完全使该函数静音,您可以简单地注释掉该行。您甚至可以使用控制语句,使其仅打印 IF 并且在满足条件时,否则它保持空白并仅返回数字。