如何防止打印function?

是否可以使function静音 ? 例如:

#include  int function(){ printf("BLAH!"); return 10; } int main(){ printf("%d", silence( function()) ); return 0; } 

而不是:

 BLAH! 10 

我会得到:

 10 

可能吗? 如果积极怎么办呢?

一个非常复杂的方法来做你想要的几乎是使用dup2()系统调用。 这需要执行fflush(stdout); dup2(silentfd, stdout); fflush(stdout); dup2(silentfd, stdout); function()之前,然后复制: fflush(stdout); dup2(savedstdoutfd, stdout); fflush(stdout); dup2(savedstdoutfd, stdout); 。 所以不可能只做silence(function()) ,因为这个构造只允许在执行了function()之后执行代码。

必须事先准备文件描述符silentfdsavedstdoutfd (未经测试的代码):

  int silentfd = open("/dev/null",O_WRONLY); int savedstdoutfd = dup(stdout); 

这几乎肯定不是你真正想要的,但是因为你的问题被称为“有可能吗?”,答案是“几乎”。

使用宏函数和null设备。

例如窗户

 #include  #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; } 

不可能。 但是,您可以尝试暂时将stdout重定向到其他位置。 这可能接近你想要的。

您可以使用此宏而不是printf来阻止打印:

 int flag=0; #define PRINT(...) if(flag){printf(...)} 

然后通过考虑变量flag使用PRINT宏。 如果flag==1 ,则函数将打印,如果flag==0 ,则不会打印该函数。

使用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) 

只有当它的参数X是一个int表达式(或使用typeof )时, silence宏才有效。我还假设从不使用printf的结果。 回想一下,“递归”宏是经过特殊预处理的, printf的内部出现(在printf宏中)是逐字记录的,没有宏扩展。

请注意, silence不能是一个函数(否则,它的参数将在调用之前进行评估)。 并且您需要GCC 语句表达式扩展来“记住”某个变量_x中的参数结果(您可以使用__COUNTER__和预处理器连接生成该名称),以将其作为__COUNTER__宏调用的值返回。

然后你需要定义你的函数quiet()verbose() ,或许类似的东西

 void quiet() { silent = true; } void verbose() { silent = false, } 

如果您不想将printf定义为宏,可以在stdout上使用freopen(3) (可能使用"/dev/null"等…)或者执行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打印而不是printf ….)

如果您正在设计该function,请执行以下操作:

 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不是你可以控制的,那么已发布的答案都是正确的解决方案。


实际上,如果你自己设计这个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或您想要使用的任何其他function。

不幸的是,如果你有明确的打印function,并像这样调用它,它将始终打印。 如果你想完全沉默这个函数,你可以简单地注释掉那一行。你甚至可以使用一个控制语句,这样它只打印IF并满足条件,否则它会保持空白并只返回数字。