12

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

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

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

而不是:

BLAH!
10

我会得到:

10

是否可以?如果阳性怎么办?

4

7 回答 7

10

几乎可以完成您想要的操作的一种非常复杂的方法是使用dup2()系统调用。这需要在调用fflush(stdout); dup2(silentfd, stdout);之前执行,然后再复制回来: . 所以不可能像 just 那样做,因为这个结构只允许在已经执行后执行代码。function()fflush(stdout); dup2(savedstdoutfd, stdout);silence(function())function()

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

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

这几乎肯定不是您真正想要的,但只要您的问题被表述为“可能吗?”,答案就是“几乎”。

于 2013-05-11T14:56:39.827 回答
8

使用宏功能和空设备。

例如对于窗户

#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;
}
于 2013-05-11T15:44:44.783 回答
5

不,它不可能。但是,您可以尝试将标准输出临时重定向到其他内容。这可能接近你想要的。

于 2013-05-11T14:52:53.213 回答
5

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

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

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

于 2013-05-11T14:59:41.097 回答
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是假的,任何非零(或!0)值都是真。我的上述建议很容易出错,因为您必须能够模仿您希望使用的任何其他功能的printf签名。silence

于 2013-05-11T15:49:55.867 回答
3

使用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宏才会起作用我还假设从未使用过的结果。回想一下,“递归”宏是经过特殊预处理的,(在那个宏中)的内部出现是逐字保留的,没有宏扩展。Xintprintfprintfprintf

请注意 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 编译器(或请别人来做)。请注意,printfGCC 知道这一点。

实际上,您应该定义自己的宏,例如

#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功能,但我不建议这样做。

(请注意,事情可能更复杂,您可以使用fputsnot printf.... 进行打印。)

于 2013-05-11T21:58:03.173 回答
0

不幸的是,如果您有明确打印的函数并像这样调用它,那么它将始终打印。如果您想完全使该函数静音,您可以简单地注释掉该行。您甚至可以使用控制语句,使其仅打印 IF 并且在满足条件时,否则它保持空白并仅返回数字。

于 2013-05-11T14:52:48.027 回答