Re: switching stdout to a file

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



On Fri, 06 May 2005 04:03:51 GMT, Norm Dresner wrote:

> /* The MSDN Library 10/2001 gives this example for the use of dup()/dup2()
> to make "stdout" refer to a program-determined file and then restores it
> NOTE: All error checking deleted for "clarity" Also, the type and
> arguments
> of main are not proper either (that's the way it was there) */
>
> #include <io.h>
> #include <stdlib.h>
> #include <stdio.h>
>
> void main( void )
> {
> int old;
> FILE *new;
>
> old = _dup( 1 ); /* "old" now refers to "stdout" */
> /* Note: file handle 1 == "stdout" */
>
> new = fopen( "data", "w" );
>
> /* stdout now refers to file "data" */
> _dup2( _fileno( new ), 1 );
>
> puts( "This goes to file 'data'\r\n" );
>
> fclose( new );
>
> /* Restore original stdout */
> _dup2( old, 1 );
> }
>
>
>
>
> /* BUT I'd like to know what's wrong with using this method instead */
>
> void main(void)
> {
> FILE *savestdout = stdout;
> stdout = fopen( "data" , "w" );
> ...
> fclose( stdout );
> stdout = savestdout;
> }
>
>
>
> TIA
> Norm

The second method isn't guaranteed to work. First, stdout is only required
to be an *expression* of type FILE*. It needn't be an actual pointer
lvalue. In fact, VC's <stdio.h> defines it like this:

#define stdout (&_iob[1])

That's an rvalue, and you can't assign to it. Second, and this is getting
even more into implementation details, stdout is hardcoded to file
descriptor 1. So code that uses _write(1) wouldn't notice your change to
stdout, nor would code that directly uses &_iob[1], such as one weird
function in <wchar.h>. Your next question should be, "What about *stdout =
*fp?" That's actually suggested in a KB article or two IIRC, but I'm trying
to forget it. As FILE is an "object type", the assignment should work, but
the C Standard says, "The address of the FILE object used to control a
stream may be significant; a copy of a FILE object may not necessarily
serve in place of the original." So I'd regard it as very non-portable at
best. To conclude, use the venerable dup/dup2 method, which is non-standard
but very portable. There's also the standard freopen, but that function
irreversibly closes the stream you're trying to redirect.

--
Doug Harrison
Microsoft MVP - Visual C++
.



Relevant Pages

  • Re: Custom Formatting The Output Of subprocess.Popen
    ... stdout and stderr specify the executed programs' standard ... Valid values are PIPE, an existing file descriptor (a positive ... integer), an existing file object, and None. ...
    (comp.lang.python)
  • Re: How to access the stdout file
    ... Standard C doesn't know a thing about directories. ... I understand that stdout is a pointer to a file, ... the object 'stdout' points to a FILE object which holds meta ... Trying to read an output stream like stdout will produce ...
    (comp.lang.c)
  • Re: Custom Formatting The Output Of subprocess.Popen
    ... stdout and stderr specify the executed programs' standard ... Valid values are PIPE, an existing file descriptor (a positive ... integer), an existing file object, and None. ...
    (comp.lang.python)
  • Re: function calls, mandatory compiler promotion of int arguments to size_t?
    ... void main{ ... fwrite(buffer, size, count, stdout); ... I know what you're saying, but in this instance I really did intend that it be one big write. ... In this instance a failure is a failure and that extra information is not needed. ...
    (comp.lang.c)
  • Re: Designation standard output as File type
    ... PrintStream. ... The first line of javadoc for java.io.File makes this clear: ... stdout is not a path name. ... There is no path for stdout, so there is no File object that ...
    (comp.lang.java.programmer)