Reputation: 893
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?
Upvotes: 12
Views: 8012
Reputation: 28845
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.
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.
Upvotes: 3
Reputation: 80355
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.
The file descriptors silentfd
and savedstdoutfd
have to be prepared in advance (untested code):
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”.
Upvotes: 10
Reputation: 1
With GCC extensions, you might consider having macros like
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.
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.
Then you need to define your functions quiet()
and verbose()
, perhaps something like
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).
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.
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.
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.
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.
You could also re-implement your own printf
function, but I don't advise doing that.
(Notice that things could be more complex, you can print using fputs
not printf
....)
Upvotes: 3
Reputation: 40155
use macro function and null device.
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;
}
Upvotes: 8
Reputation: 732
You can use this macro instead of printf
to be able to prevent printing:
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.
Upvotes: 5
Reputation: 16224
No its not possible. You could however try to temporarily redirect the stdout to something else. That may come close to what you want.
Upvotes: 5
Reputation: 852
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.
Upvotes: 0