14

I want to call bar() in foo(), bar() will change some global variables' values(this is what I want), but meanwhile produce some output( I dont' want any output);

void foo() 
{
    //I have tried:
    //system("1>&/dev/null") and of course this won't work
    bar();
}

What can I do to suppress bar()'s output?

CDT
  • 10,165
  • 18
  • 66
  • 97

1 Answers1

19

You can save the global variable stdout before bar();, then set it to /dev/null, then restore it. Code example;

#include <stdio.h>

int main() {
    int old_stdout = dup(1);

    freopen ("/dev/null", "w", stdout); // or "nul" instead of "/dev/null"
    printf("asd1");
    fclose(stdout);

    stdout = fdopen(old_stdout, "w"); 
    printf("asd2");
    return 0;
}

Tested on OS X, not sure about Windows.

EDIT: You can replace /dev/null with nul on Windows. As for the fdopen() and dup() working under Windows - they're part of the POSIX.1 standard according to my man pages, but I haven't tested it.

EDIT 2: As suggested in the comments, if the solution does not work for Windows, there's another suggestion in this SO answer.

EDIT 3: A longer, though standard compliant and cross-platform way to do this is as following. (code adapted from mentioned SO question, and Microsoft's documentation for _dup)

#include <stdio.h>

#ifdef _WIN32
#include <io.h>
char * const nulFileName = "NUL";
#define CROSS_DUP(fd) _dup(fd)
#define CROSS_DUP2(fd, newfd) _dup2(fd, newfd)
#else
#include <unistd.h>
char * const nulFileName = "/dev/null";
#define CROSS_DUP(fd) dup(fd)
#define CROSS_DUP2(fd, newfd) dup2(fd, newfd)
#endif

int main() {
    int stdoutBackupFd;
    FILE *nullOut;
    /* duplicate stdout */
    stdoutBackupFd = CROSS_DUP(STDOUT_FILENO);

    fflush(stdout);
    nullOut = fopen(nulFileName, "w");
    CROSS_DUP2(fileno(nullOut), STDOUT_FILENO);

    printf("asd1\n");
    fflush(stdout);
    fclose(nullOut);

    // Restore stdout
    CROSS_DUP2(stdoutBackupFd, STDOUT_FILENO);
    close(stdoutBackupFd);

    printf("asd2\n");

    return 0;
}

The flushes are required to make sure that (1) anything printed before switching stdout is indeed printed to screen, and (2) nothing that was printed before switching back stdout to console (or pipe) is printed.

Community
  • 1
  • 1
user1071136
  • 15,636
  • 4
  • 42
  • 61
  • 1
    Might work under Unix based systems (Linux, Mac OS X). Will never work under Windows, since in the windows world file paths like "/dev/null" are not possible. – Lukas Schmelzeisen Nov 21 '12 at 17:15
  • Can `stdout` be assigned the way you do in the `fdopen` call? Does the standard specify that stdout has to be a `l-value`? Would better to do it this way - http://stackoverflow.com/a/7664951/922712 – user93353 Nov 21 '12 at 17:32
  • Pretty sure reassigning `stdout` is undefined behavior. The standard just says that `stdout` is a macro resolving to an expression of type `FILE*`. It doesn't have to be an lvalue, for example that could be the result of a function call, in which case it's not assignable. – asveikau Nov 21 '12 at 18:45
  • @user93353: you're right, fixed my answer, and added cross-platform handling. – user1071136 Nov 23 '12 at 15:06
  • hm, neither the fancy nor plain aproach here work for me on macos. – orion elenzil Feb 08 '19 at 01:02
  • .. i take that back. the fancy approach worked great. – orion elenzil Feb 08 '19 at 01:07