如何防止功能无法打印?(How to prevent function from printing?

2019-09-02 15:25发布

是否有可能以沉默的功能? 例如:

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

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

而不是:

BLAH!
10

我会得到:

10

可能吗? 如果正怎么办呢?

Answer 1:

一种非常复杂的方式做几乎你想要的是使用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);

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



Answer 2:

使用微距功能和空设备。

例如,对于窗户

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


Answer 3:

没有它不可能。 但是,您可以尝试到标准输出临时重定向到别的东西。 这可能会接近你想要什么。



Answer 4:

你可以使用这个宏而不是printf是能防止印刷:

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

然后通过考虑变量使用PRINT宏flag 。 如果flag==1 ,该功能将打印,如果flag==0 ,该功能将无法打印。



Answer 5:

随着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)

silence宏将只工作,如果它的参数Xint表达(或使用typeof运算 )我还假设的结果printf从未使用过。 回想一下,“递归”的宏专门预处理,内部发生printf (在printf宏)被逐字左无宏观扩展。

请注意, silence不能是一个函数(否则,它的参数将被调用前评估)。 而你需要GCC 的语句表达式扩展“记住”在一些变量参数的结果_x (你可以生成使用该名称__COUNTER__和预处理串联),给它早在价值silence宏调用。

然后,你需要定义函数quiet()verbose()也许像

void quiet() 
{
   silent = true;
}

void verbose()
{
   silent = false,
}

如果你不希望定义printf为您的宏,你可以使用freopen函数(3)在stdout (也许"/dev/null"等)或做DUP2(2)技巧(如帕斯卡Cuoq建议 ) 。

如果你的代码库是巨大的,你想要的东西更严重,并愿意花费几天或几周的工作,考虑与插件或定制您的GCC编译器MELT扩展(或要求别人做到这一点)。 请注意, 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函数,但我不建议这样做。

(请注意,情况可能会更复杂,你可以打印使用fputsprintf ....)



Answer 6:

如果你设计的功能做到以下几点:

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 )值是true。 我的上述建议是容易出错的,因为你必须要能够模仿printf签名silence或您希望使用其它任何功能。



Answer 7:

不幸的是,如果你有明确的功能和打印这样称呼它,然后它会永远打印。 如果你想保持沉默的功能完全,你可以简单地注释掉line.You甚至可以使用控制语句,以便只打印如果当一个条件被满足,否则它保持空白,只返回数量。



文章来源: How to prevent function from printing?
标签: c gcc printf