5

I have three files as below

Test.cpp

void helloworld()
{
    disable pf;
    pf.Disable();
    printf("No statement \n");
    }
int main()
{
    disable dis;
    helloworld();
    printf("Hello World");
    system("pause");
    return 0;
}

disable.cpp

    #include "StdAfx.h"
    #include "disable.h"
    disable::disable(void)
    {#define printf(fmt, ...) (0)}
    disable::~disable(void)
   {}
   void disable::Disable()
   {
    #define printf(fmt, ...) (0)
    }

disable.h

#pragma once
class disable
{
public:
    disable(void);
    ~disable(void);
    void Disable();
};

After executing, I am getting output as No Statement Hello World. But I would like to disable these two printf statements by calling Disable function and disable constructor.. Please help me why it is not working and how to solve this. Please help.

But things works fine if I do like

main()
{
#define printf(fmt, ...) (0)
printf("Hello World");
}

But why not if I am calling it from a function?

tomahh
  • 13,441
  • 3
  • 49
  • 70
Rasmi Ranjan Nayak
  • 11,510
  • 29
  • 82
  • 122
  • 3
    Where are you going with all this? Is there some practical end you're pursuing, or is this purely an academic exercise? – NPE Dec 11 '12 at 09:14
  • 1
    Preprocessing comes before compilation. It doesn't matter whether it's in a function or not. That function is empty to the compiler. – chris Dec 11 '12 at 09:14
  • Rule of thumb: every `printf` format string should end with `\n`, or else you should call `fflush` after the `printf` – Basile Starynkevitch Dec 11 '12 at 09:14

4 Answers4

10

You can disable the printf ouput by:

close(STDOUT_FILENO);

or you can use also:

fclose(stdout);

This will disable all output to the stdout

Example:

#include<stdio.h>
#include<stdlib.h>

int main(){
    printf ("This message will be displayed\n");
    fclose(stdout);
    printf ("This message will not be displayed\n");
    // to reopen the stdout, this is another question
    return 0;
}

Note

If you are using sockets in your program, than you have to be careful here because the close of stout will cause the redirection of the output to the sockets

MOHAMED
  • 41,599
  • 58
  • 163
  • 268
  • Could u pls elaborate more? – Rasmi Ranjan Nayak Dec 11 '12 at 09:24
  • There's no guarantee that this will work, or even that it will compile---`close` and `STDOUT_FILENO` are Unix specific. – James Kanze Dec 11 '12 at 10:18
  • there is also `fclose(stdout);` – MOHAMED Dec 11 '12 at 10:19
  • @MohamedKALLEL That's guaranteed to work. On the other hand, it makes it impossible to restore the original output later. – James Kanze Dec 11 '12 at 10:24
  • @MohamedKALLEL: If we want to reopen then how can we do that... Do we nned to use fopen()..? – Rasmi Ranjan Nayak Dec 11 '12 at 10:52
  • @RasmiRanjanNayak It depends on your system (Windows/Linux..) and the output device (console, screen ). example if you are using linux and console than to reopn it you have to do in this way `stdout = fopen("/dev/tty","w");`. – MOHAMED Dec 11 '12 at 10:55
  • I am using `Windows` and my output device is both in `consloe` and `screen` – Rasmi Ranjan Nayak Dec 11 '12 at 10:56
  • @RasmiRanjanNayak I could not help you for windows. This could be another question. BTW I see an answer in this topic wich suggest to you to redirect the output to a file and then get back to the stdout. ths could be also an alternate solution for you. and you can add to this solution the remove of file when you get back to the stdout – MOHAMED Dec 11 '12 at 11:11
  • @RasmiRanjanNayak: It will be good fro you If you update this topic with the results you found – MOHAMED Dec 11 '12 at 12:40
5

A macro doesnt obey scope rules, c++ syntax rules, or anything. It is a text replacement engine, only.

When you say #define printf(fmt, ...) (0) in disable.cpp, it is defined ONLY in disable.cpp. If you were to write that in disable.h, it would be defined in all files that include from disable.h.

The only way to control a macro is with a macro (#if and #ifdef and their ilk). So what you want to to can be achieved by the following.

#define DISABLE_PRINTF

#ifdef DISABLE_PRINTF
    #define printf(fmt, ...) (0)
#endif

But this will be a global disable and can only be undone by commenting out the first #define and recompiling the code. There is no way to do selective/scope based control of disabling using macros.

Edit: Instead of redefining printf itself, it is recommended to write a wrapper which is defined in terms of printf for this purpose.

Karthik T
  • 31,456
  • 5
  • 68
  • 87
  • @KarthikT: Can I write an `inline function` which can disable that for me at run time? – Rasmi Ranjan Nayak Dec 11 '12 at 09:22
  • @RasmiRanjanNayak as I said, you cannot use macros for any sort of selective control, you cannot disable at some places but enable at other places, especially not with a function, since macros dont obey function rules/syntax. You would be better off seeing if Mohamed KALLEL's solution works if you want localized control. – Karthik T Dec 11 '12 at 09:25
  • Note too that doing this is undefined behavior, at least according to the standard. (I can't imagine it actually causing a problem, but you never know.) – James Kanze Dec 11 '12 at 10:15
  • @JamesKanze could you elabourate? – Karthik T Dec 11 '12 at 10:17
  • @KarthikT What's to elaborate? You're not allowed to (re)define functions in the standard library; other standard library functions may use them (including in a template or an inline function). It's probably without risk, however, because I can't imagine anything in the standard library using `printf`. – James Kanze Dec 11 '12 at 10:20
  • @JamesKanze I see your point, as this [similar post](http://stackoverflow.com/questions/5765175/macro-to-turn-off-printf-statements) points out as well, if this were defined before were included, results would be chaos – Karthik T Dec 11 '12 at 10:28
2

On implementations that support it, you could redirect the stdout buffer to "disable" the console, and restore it when you want to "enable" it again. Here's a code sample which works (at least) on Linux with gcc.

NOTE This is a implementation-specific solution and uses dup() and dup2() from unistd.h. It is not guaranteed by the standard to work everywhere.

#include <cstdio>
#include <unistd.h>

int main() {
    printf("Hello world.\n");
    fpos_t pos;
    fgetpos(stdout, &pos);  // save the position in the file stream
    int fd = dup(fileno(stdout));  // use the dup() function to create a copy of stdout

    freopen("dummy.txt", "w", stdout);  // redirect stdout
    printf("Hello nobody.\n");  // this is not printed to the "usual" stdout

    fflush(stdout);   
    dup2(fd, fileno(stdout));  // restore the stdout
    close(fd);
    clearerr(stdout);  

    fsetpos(stdout, &pos); // move to the correct position
    printf("Hello world again.\n");  // this is printed back to the "usual" stdout
}

You could put that logic into enable() and disable() functions. Let me emphasise, this is an implementation-specific solution. I am not aware of any standard-conforming solution to restore the standard streams after they have been redirected.

Masked Man
  • 1
  • 7
  • 40
  • 80
  • I updated the answer. Note that this is an implementation-specific solution. – Masked Man Dec 11 '12 at 10:16
  • This would be easy if he were using `std::cout`, but how can you do this from within the program for `printf`? – James Kanze Dec 11 '12 at 10:17
  • @JamesKanze My example uses `printf`. I cannot emphasise enough this is an implementation-specific solution, so take it with a pinch of salt. :) – Masked Man Dec 11 '12 at 10:19
  • I am not very comfortable providing implementation-specific solutions, but I suppose there's no harm in mentioning it at least. For all you know, the OP's program may never be used outside a specific environment. – Masked Man Dec 11 '12 at 10:21
0

in my similar case "printf(fmt, ...) (0)" did not compile ,but it worked like this:

#if RELEASE == 1  // no printf at release
 int printf(const char *__restrict, ...)  {  return 0; }
#endif 
jkr
  • 1