是否可以静音一个功能? 例如:
#include <stdio.h>
int function(){
printf("BLAH!");
return 10;
}
int main(){
printf("%d", silence( function()) );
return 0;
}
而不是:
BLAH!
10
我会得到:
10
有可能吗?如果积极怎么办呢?
答案 0 :(得分:10)
一种非常复杂的方法,几乎可以使用dup2()系统调用。这需要在调用fflush(stdout); dup2(silentfd, stdout);
之前执行function()
,然后在之后复制:fflush(stdout); dup2(savedstdoutfd, stdout);
。所以不可能只做silence(function())
,因为这个构造只允许在function()
执行后执行代码。
文件描述符silentfd
和savedstdoutfd
必须事先准备好(未经测试的代码):
int silentfd = open("/dev/null",O_WRONLY);
int savedstdoutfd = dup(stdout);
这几乎肯定不是你真正想要的,但是因为你的问题被称为“有可能吗?”,答案是“差不多”。
答案 1 :(得分:8)
使用宏功能和空设备。
E.g。对于Windows
#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;
}
答案 2 :(得分:5)
不可能。但是,您可以尝试暂时将stdout重定向到其他内容。这可能接近你想要的。
答案 3 :(得分:5)
您可以使用此宏而不是printf
来阻止打印:
int flag=0;
#define PRINT(...) if(flag){printf(...)}
然后通过考虑变量flag
来使用PRINT宏。如果flag==1
,则会打印该功能,如果flag==0
,则无法打印该功能。
答案 4 :(得分:3)
如果您正在设计该功能,请执行以下操作:
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
为false且任何非零(或!0
)值为true。我的上述建议容易出错,因为您必须能够模仿printf
的{{1}}签名或您希望使用的任何其他功能。
答案 5 :(得分:3)
使用GCC extensions,您可能会考虑使用像
这样的宏bool silent;
#define silence(X) ({int _x; quiet(); _x = (X); verbose(); _x; })
#define printf(Fmt,...) \
do{if (!silent) printf(Fmt,##__VA_ARGS__);}while(0)
silence
宏仅在其参数X
为int
表达式(或使用typeof)时才有效。我还假设printf
的结果永远不会使用1}}。回想一下,“递归”宏是经过特殊预处理的,printf
(在printf
宏中)的内部出现是逐字记录而没有宏扩展。
请注意,silence
不能是一个函数(否则,在调用它之前,它的参数将被评估)。并且您需要GCC statement expressions扩展来“记住”某个变量_x
中的参数结果(您可以使用__COUNTER__
和预处理器连接生成该名称),并将其作为silence
宏调用的值。
然后你需要定义你的函数quiet()
和verbose()
,或许类似
void quiet()
{
silent = true;
}
void verbose()
{
silent = false,
}
如果您不想将printf
定义为您的宏,可以在stdout
上使用freopen(3)(可能使用"/dev/null"
等...)或执行{ {3}}技巧(如dup2(2))。
如果您的代码库很大,并且您想要更严肃的事情并愿意花费数天或数周的工作时间,请考虑使用插件或suggested by Pascal Cuoq扩展程序自定义GCC编译器(或要求某人执行此操作) )。请注意,GCC已知printf
。
实际上,您应该定义自己的宏,如
#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扩展来接受MELT到可变参数宏。如果你想要严格的C99,你只需说__VA_ARGS__
,每个dbgprintf
在格式后需要一个参数。
您也可以重新实现自己的printf
功能,但我不建议您这样做。
(请注意事情可能更复杂,您可以使用fputs
而不是printf
进行打印....)
答案 6 :(得分:0)
不幸的是,如果您有明确打印的功能并像这样调用它,那么它将始终打印。如果你想完全沉默这个函数,你可以简单地注释掉那一行。你甚至可以使用一个控制语句,这样它只打印IF,当条件满足时,否则它会保持空白,只返回数字。