是否有可能以沉默的功能? 例如:
#include <stdio.h>
int function(){
printf("BLAH!");
return 10;
}
int main(){
printf("%d", silence( function()) );
return 0;
}
而不是:
BLAH!
10
我会得到:
10
可能吗? 如果正怎么办呢?
是否有可能以沉默的功能? 例如:
#include <stdio.h>
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()
已经执行。
文件描述符silentfd
和savedstdoutfd
具有提前(未测试的代码),以制备:
int silentfd = open("/dev/null",O_WRONLY);
int savedstdoutfd = dup(stdout);
这是几乎可以肯定不是你真正想要的,但因为你的问题被表述为“这可能吗?”,答案是“差不多”。
使用微距功能和空设备。
例如,对于窗户
#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;
}
没有它不可能。 但是,您可以尝试到标准输出临时重定向到别的东西。 这可能会接近你想要什么。
你可以使用这个宏而不是printf
是能防止印刷:
int flag=0;
#define PRINT(...) if(flag){printf(...)}
然后通过考虑变量使用PRINT宏flag
。 如果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)
这silence
宏将只工作,如果它的参数X
是int
表达(或使用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
函数,但我不建议这样做。
(请注意,情况可能会更复杂,你可以打印使用fputs
不printf
....)
如果你设计的功能做到以下几点:
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
或您希望使用其它任何功能。
不幸的是,如果你有明确的功能和打印这样称呼它,然后它会永远打印。 如果你想保持沉默的功能完全,你可以简单地注释掉line.You甚至可以使用控制语句,以便只打印如果当一个条件被满足,否则它保持空白,只返回数量。