如何防止打印功能?

时间:2013-05-11 14:50:47

标签: c gcc printf

是否可以静音一个功能? 例如:

#include <stdio.h>
int function(){
  printf("BLAH!");
  return 10;

}
int main(){
  printf("%d", silence( function()) );
return 0;
}

而不是:

BLAH!
10

我会得到:

10

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

7 个答案:

答案 0 :(得分:10)

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

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

 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宏仅在其参数Xint表达式(或使用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,当条件满足时,否则它会保持空白,只返回数字。