Is it possible to silence a function? For example:
是否可以使功能静音?例如:
#include <stdio.h>
int function(){
printf("BLAH!");
return 10;
}
int main(){
printf("%d", silence( function()) );
return 0;
}
And instead of:
而不是:
BLAH!
10
I would get:
我会得到:
10
Is it possible? If positive how to do it?
可能吗?如果积极怎么办呢?
7 个解决方案
#1
10
An awfully complicated way to do almost what you want is to use the dup2() system call. This requires executing fflush(stdout); dup2(silentfd, stdout);
before function()
is called, and copying back afterwards: fflush(stdout); dup2(savedstdoutfd, stdout);
. So it is not possible to do as just silence(function())
, since this construct only allows to execute code after function()
has already been executed.
一个非常复杂的方法来做你想要的几乎是使用dup2()系统调用。这需要执行fflush(stdout); dup2(silentfd,stdout);调用function()之前,然后复制:fflush(stdout); dup2(savedstdoutfd,stdout);.所以不可能只做静默(function()),因为这个构造只允许在执行了function()之后执行代码。
The file descriptors silentfd
and savedstdoutfd
have to be prepared in advance (untested code):
必须事先准备文件描述符silentfd和savedstdoutfd(未经测试的代码):
int silentfd = open("/dev/null",O_WRONLY);
int savedstdoutfd = dup(stdout);
This is almost certainly not what you really want, but inasmuch as your question is phrased as “is it possible?”, the answer is “almost”.
这几乎肯定不是你真正想要的,但是因为你的问题被称为“有可能吗?”,答案是“几乎”。
#2
8
use macro function and null device.
使用宏函数和null设备。
E.g. for 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;
}
#3
5
No its not possible. You could however try to temporarily redirect the stdout to something else. That may come close to what you want.
不可能。但是,您可以尝试暂时将stdout重定向到其他位置。这可能接近你想要的。
#4
5
You can use this macro instead of printf
to be able to prevent printing:
您可以使用此宏而不是printf来阻止打印:
int flag=0;
#define PRINT(...) if(flag){printf(...)}
then use PRINT macro by considering the variable flag
. If flag==1
, the function will print and if flag==0
, the function will not print.
然后通过考虑变量标志来使用PRINT宏。如果flag == 1,则函数将打印,如果flag == 0,则不会打印该函数。
#5
3
With GCC extensions, you might consider having macros like
使用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)
that silence
macro would work only if its argument X
is a int
expression (or use typeof) I also assume that the result of printf
is never used. Recall that "recursive" macros are specially pre-processed, the inside occurrence of printf
(in that printf
macro) is left verbatim without macro-expansion.
只有当它的参数X是一个int表达式(或使用typeof)时,沉默宏才有效。我还假设从不使用printf的结果。回想一下,“递归”宏是经过特殊预处理的,printf的内部出现(在printf宏中)是逐字记录的,没有宏扩展。
Notice that silence
cannot be a function (otherwise, its argument would have been evaluated before calling it). And you need GCC statement expressions extension to "remember" the result of the argument in some variable _x
(you could generate that name using __COUNTER__
and preprocessor concatenation), to give it back as the value of silence
macro invocation.
请注意,沉默不能是一个函数(否则,它的参数将在调用之前进行评估)。并且您需要GCC语句表达式扩展来“记住”某个变量_x中的参数结果(您可以使用__COUNTER__和预处理器连接生成该名称),以将其作为静态宏调用的值返回。
Then you need to define your functions quiet()
and verbose()
, perhaps something like
然后你需要定义你的函数quiet()和verbose(),或许类似的东西
void quiet()
{
silent = true;
}
void verbose()
{
silent = false,
}
if you don't want to define printf
as your macro, you could use freopen(3) on stdout
(perhaps with "/dev/null"
etc...) or do dup2(2) tricks (like suggested by Pascal Cuoq).
如果您不想将printf定义为宏,可以在stdout上使用freopen(3)(可能使用“/ dev / null”等...)或者执行dup2(2)技巧(如Pascal Cuoq建议) 。
If your code base is huge, and you want something more serious and are willing to spend days or weeks of work, consider customizing your GCC compiler with a plugin or a MELT extension (or ask someone to do it). Notice that printf
is known to GCC.
如果您的代码库很大,并且您想要更严肃的事情并且愿意花费数天或数周的工作,请考虑使用插件或MELT扩展来定制您的GCC编译器(或要求某人执行此操作)。请注意,printf是GCC已知的。
In reality, you should define your own macro like
实际上,您应该定义自己的宏
#define myprintf(Fmt, ...) do{if (!silent) \
printf(Fmt,__VA_ARGS__);}while(0)
and just use myprintf
instead of printf
everywhere, this is a portable trick. Of course, I assume you are not passing printf
as a function pointer.
并且只是在任何地方使用myprintf而不是printf,这是一个便携式技巧。当然,我假设您没有将printf作为函数指针传递。
For debugging, I actually recommend
对于调试,我实际上建议
#define dbgprintf(Fmt,...) do{if (wantdebug) \
printf("%s:%d:" Fmt "\n", __FILE__, __LINE__, \
##__VA_ARGS__);}while(0)
and then I use dbgprintf("i=%d",i)
or simply dbgprintf("foo here")
in my code.
然后我在我的代码中使用dbgprintf(“i =%d”,i)或简单地使用dbgprintf(“foo here”)。
I'm using ##__VA_ARGS__
which is a GCC extension to accept no variable arguments to a variadic macro. If you want strict C99, you will just say __VA_ARGS__
and every dbgprintf
would need one argument after the format.
我正在使用## __ VA_ARGS__这是一个GCC扩展,不接受可变参数宏的变量参数。如果你想要严格的C99,你只需说__VA_ARGS__并且每个dbgprintf在格式之后需要一个参数。
You could also re-implement your own printf
function, but I don't advise doing that.
您也可以重新实现自己的printf函数,但我不建议这样做。
(Notice that things could be more complex, you can print using fputs
not printf
....)
(请注意,事情可能更复杂,您可以使用fput打印而不是printf ....)
#6
3
If you're designing the function do the following:
如果您正在设计该功能,请执行以下操作:
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;
}
That should do what you're looking for. Unfortunately, I didn't test it and my C is probably a little bit rusty.
那应该做你想要的。不幸的是,我没有测试它,我的C可能有点生锈。
Of course if function
isn't something you have control over, the answers already posted are all correct solutions.
当然,如果功能不是你可以控制的,那么已发布的答案都是正确的解决方案。
Actually, if you're designing the function yourself, just do:
实际上,如果你自己设计这个功能,那就做:
int function(int print){
if (print)
printf("BLAH!");
return 10;
}
function(0); /* Won't print anything */
function(!0); /* Will print "BLAH!" */
because 0
is false and any non-zero (or !0
) value is true. My above suggestion is error prone since you'll have to be able to mimic the printf
signature for silence
or for any other function you wish to use.
因为0为假,任何非零(或!0)值为真。我的上述建议很容易出错,因为您必须能够模仿printf签名以保持静音或您想要使用的任何其他功能。
#7
0
Unfortunately if you have the function explicitly printing and call it like this then it will always print. if you want to silence the function completely you could simply comment out that line.You could even use a control statement so that it only prints IF and when a condition is met otherwise it stays blank and only returns the number.
不幸的是,如果你有明确的打印功能,并像这样调用它,它将始终打印。如果你想完全沉默这个函数,你可以简单地注释掉那一行。你甚至可以使用一个控制语句,这样它只打印IF,当条件满足时,否则它会保持空白,只返回数字。
#1
10
An awfully complicated way to do almost what you want is to use the dup2() system call. This requires executing fflush(stdout); dup2(silentfd, stdout);
before function()
is called, and copying back afterwards: fflush(stdout); dup2(savedstdoutfd, stdout);
. So it is not possible to do as just silence(function())
, since this construct only allows to execute code after function()
has already been executed.
一个非常复杂的方法来做你想要的几乎是使用dup2()系统调用。这需要执行fflush(stdout); dup2(silentfd,stdout);调用function()之前,然后复制:fflush(stdout); dup2(savedstdoutfd,stdout);.所以不可能只做静默(function()),因为这个构造只允许在执行了function()之后执行代码。
The file descriptors silentfd
and savedstdoutfd
have to be prepared in advance (untested code):
必须事先准备文件描述符silentfd和savedstdoutfd(未经测试的代码):
int silentfd = open("/dev/null",O_WRONLY);
int savedstdoutfd = dup(stdout);
This is almost certainly not what you really want, but inasmuch as your question is phrased as “is it possible?”, the answer is “almost”.
这几乎肯定不是你真正想要的,但是因为你的问题被称为“有可能吗?”,答案是“几乎”。
#2
8
use macro function and null device.
使用宏函数和null设备。
E.g. for 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;
}
#3
5
No its not possible. You could however try to temporarily redirect the stdout to something else. That may come close to what you want.
不可能。但是,您可以尝试暂时将stdout重定向到其他位置。这可能接近你想要的。
#4
5
You can use this macro instead of printf
to be able to prevent printing:
您可以使用此宏而不是printf来阻止打印:
int flag=0;
#define PRINT(...) if(flag){printf(...)}
then use PRINT macro by considering the variable flag
. If flag==1
, the function will print and if flag==0
, the function will not print.
然后通过考虑变量标志来使用PRINT宏。如果flag == 1,则函数将打印,如果flag == 0,则不会打印该函数。
#5
3
With GCC extensions, you might consider having macros like
使用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)
that silence
macro would work only if its argument X
is a int
expression (or use typeof) I also assume that the result of printf
is never used. Recall that "recursive" macros are specially pre-processed, the inside occurrence of printf
(in that printf
macro) is left verbatim without macro-expansion.
只有当它的参数X是一个int表达式(或使用typeof)时,沉默宏才有效。我还假设从不使用printf的结果。回想一下,“递归”宏是经过特殊预处理的,printf的内部出现(在printf宏中)是逐字记录的,没有宏扩展。
Notice that silence
cannot be a function (otherwise, its argument would have been evaluated before calling it). And you need GCC statement expressions extension to "remember" the result of the argument in some variable _x
(you could generate that name using __COUNTER__
and preprocessor concatenation), to give it back as the value of silence
macro invocation.
请注意,沉默不能是一个函数(否则,它的参数将在调用之前进行评估)。并且您需要GCC语句表达式扩展来“记住”某个变量_x中的参数结果(您可以使用__COUNTER__和预处理器连接生成该名称),以将其作为静态宏调用的值返回。
Then you need to define your functions quiet()
and verbose()
, perhaps something like
然后你需要定义你的函数quiet()和verbose(),或许类似的东西
void quiet()
{
silent = true;
}
void verbose()
{
silent = false,
}
if you don't want to define printf
as your macro, you could use freopen(3) on stdout
(perhaps with "/dev/null"
etc...) or do dup2(2) tricks (like suggested by Pascal Cuoq).
如果您不想将printf定义为宏,可以在stdout上使用freopen(3)(可能使用“/ dev / null”等...)或者执行dup2(2)技巧(如Pascal Cuoq建议) 。
If your code base is huge, and you want something more serious and are willing to spend days or weeks of work, consider customizing your GCC compiler with a plugin or a MELT extension (or ask someone to do it). Notice that printf
is known to GCC.
如果您的代码库很大,并且您想要更严肃的事情并且愿意花费数天或数周的工作,请考虑使用插件或MELT扩展来定制您的GCC编译器(或要求某人执行此操作)。请注意,printf是GCC已知的。
In reality, you should define your own macro like
实际上,您应该定义自己的宏
#define myprintf(Fmt, ...) do{if (!silent) \
printf(Fmt,__VA_ARGS__);}while(0)
and just use myprintf
instead of printf
everywhere, this is a portable trick. Of course, I assume you are not passing printf
as a function pointer.
并且只是在任何地方使用myprintf而不是printf,这是一个便携式技巧。当然,我假设您没有将printf作为函数指针传递。
For debugging, I actually recommend
对于调试,我实际上建议
#define dbgprintf(Fmt,...) do{if (wantdebug) \
printf("%s:%d:" Fmt "\n", __FILE__, __LINE__, \
##__VA_ARGS__);}while(0)
and then I use dbgprintf("i=%d",i)
or simply dbgprintf("foo here")
in my code.
然后我在我的代码中使用dbgprintf(“i =%d”,i)或简单地使用dbgprintf(“foo here”)。
I'm using ##__VA_ARGS__
which is a GCC extension to accept no variable arguments to a variadic macro. If you want strict C99, you will just say __VA_ARGS__
and every dbgprintf
would need one argument after the format.
我正在使用## __ VA_ARGS__这是一个GCC扩展,不接受可变参数宏的变量参数。如果你想要严格的C99,你只需说__VA_ARGS__并且每个dbgprintf在格式之后需要一个参数。
You could also re-implement your own printf
function, but I don't advise doing that.
您也可以重新实现自己的printf函数,但我不建议这样做。
(Notice that things could be more complex, you can print using fputs
not printf
....)
(请注意,事情可能更复杂,您可以使用fput打印而不是printf ....)
#6
3
If you're designing the function do the following:
如果您正在设计该功能,请执行以下操作:
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;
}
That should do what you're looking for. Unfortunately, I didn't test it and my C is probably a little bit rusty.
那应该做你想要的。不幸的是,我没有测试它,我的C可能有点生锈。
Of course if function
isn't something you have control over, the answers already posted are all correct solutions.
当然,如果功能不是你可以控制的,那么已发布的答案都是正确的解决方案。
Actually, if you're designing the function yourself, just do:
实际上,如果你自己设计这个功能,那就做:
int function(int print){
if (print)
printf("BLAH!");
return 10;
}
function(0); /* Won't print anything */
function(!0); /* Will print "BLAH!" */
because 0
is false and any non-zero (or !0
) value is true. My above suggestion is error prone since you'll have to be able to mimic the printf
signature for silence
or for any other function you wish to use.
因为0为假,任何非零(或!0)值为真。我的上述建议很容易出错,因为您必须能够模仿printf签名以保持静音或您想要使用的任何其他功能。
#7
0
Unfortunately if you have the function explicitly printing and call it like this then it will always print. if you want to silence the function completely you could simply comment out that line.You could even use a control statement so that it only prints IF and when a condition is met otherwise it stays blank and only returns the number.
不幸的是,如果你有明确的打印功能,并像这样调用它,它将始终打印。如果你想完全沉默这个函数,你可以简单地注释掉那一行。你甚至可以使用一个控制语句,这样它只打印IF,当条件满足时,否则它会保持空白,只返回数字。