Thread: question about fprintf vs printf

  1. #1
    Registered User mc088's Avatar
    Join Date
    Jan 2017
    Posts
    19

    question about fprintf vs printf

    Hi,

    In error checking part of code below (where the existence of file to read is checked), my (hopefully correct) understanding is printf would print to stdout, and the fprintf statement (currently commented out) means that fprintf prints error messages to stderr.

    As I see it, both print out the "Unable to open" message so was wondering what the 'stderr' actually means, and which statement (the printf or the fprint) is the preferred choice in this case and why?

    Thanks!!

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        FILE *ofPtr;
        
        ofPtr = fopen("oldmast.dat", "r");    
    
        if ( ofPtr == NULL ) 
        {
           printf ("Unable to open oldmast.dat\n");
           // fprintf(stderr, "Unable to open oldmast.dat\n");
           exit(0);
        }
        return 0;
    }
    Last edited by mc088; 02-07-2017 at 08:15 PM.

  2. #2
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    Normally, output streams such as stdin are buffered, meaning that for efficiency reasons it doesn't output the characters to the console right away. stderr isn't, it prints it as soon as it gets it, that's the main difference. Also, if a program were to use your program's output, it wouldn't have to worry about stray warnings or errors in its stream, because they'd be output in another stream, traditionally stderr.
    Devoted my life to programming...

  3. #3
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Errors are usually output on the standard error stream. There are two main advantages to this. Firstly, the standard error stream is unbuffered so that the output is more likely to appear as soon as possible. Secondly, the standard error stream can be separately redirected so that if someone runs your program while redirecting the standard output stream to a file, the standard error stream will still appear on the terminal. Or vice versa. Or both could be redirected to separate files, or the same file, or whatever.

  4. #4
    Registered User MacNilly's Avatar
    Join Date
    Oct 2005
    Location
    CA, USA
    Posts
    466
    Which operating system defines that stderr is auto-flushed? Or is that defined by the C spec?

    From my understanding, stderr -> stdout, unless stderr has been redirected by the operating system (for example, pointing to dev/null). In general, I/O operations are buffered, so if you NEED the side-effect of print to happen immediately, you should simply follow your print call with a flush call... for any file handle.
    Last edited by MacNilly; 02-13-2017 at 04:40 PM.

  5. #5
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    If by "stderr -> stdout" you mean that they are the same, then that's not correct. They are separate streams that just happen to go to both go to the terminal by default.

    Quote Originally Posted by C11_Draft
    7.21.3

    3. When a stream is unbuffered, characters are intended to appear from the source or at the destination as soon as possible. Otherwise characters may be accumulated and transmitted to or from the host environment as a block. When a stream is fully buffered, characters are intended to be transmitted to or from the host environment as a block when a buffer is filled. When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. Furthermore, characters are intended to be transmitted as a block to the host environment when a buffer is filled, when input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment. Support for these characteristics is implementation-defined, and may be affected via the setbuf and setvbuf functions.

    7. At program startup, three text streams are predefined and need not be opened explicitly — standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output). As initially opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.
    So all the standard guarantees for standard error is that at startup it is at most line-buffered, never fully-buffered. I thought it was unbuffered, but that is apparently not guaranteed.

    But it also says that the standard error stream remains at most line-buffered when redirected to a file, which is not the case with the standard output stream. So as long as a diagnostic message has a newline after it, it should appear in the file even if there's a crash after it is printed.

  6. #6
    Registered User MacNilly's Avatar
    Join Date
    Oct 2005
    Location
    CA, USA
    Posts
    466
    Quote Originally Posted by algorism View Post
    If by "stderr -> stdout" you mean that they are the same, then that's not correct. They are separate streams that just happen to go to both go to the terminal by default.
    No, I just meant that stderr is mapped to stdout by default, unless redirected. I understand they are separate streams, which happen to map to the terminal.. thus stderr -> stdout, by default.

    In any case, can we agree that a good programming practice is to call "flush(io)" on any stream, if the intent is to immediately get the side-effect?

    Your quoted specification is a beast, with many ambiguous terms like "as soon as possible" -- that is not specific enough for programming. In any case, can we can ignore that ambiguous specification and simply call flush() after a series of print()s, and get the intended behavior?

    But hey, buffered I/O is an optimization... a leaky abstraction, that requires experience to properly understand.. That C spec does nothing to illuminate anyone, at all.
    Last edited by MacNilly; 02-13-2017 at 05:29 PM.

  7. #7
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by MacNilly View Post
    No, I just meant that stderr is mapped to stdout by default, unless redirected. I understand they are separate streams, which happen to map to the terminal.. thus stderr -> stdout, by default.

    In any case, can we agree that a good programming practice is to call "flush(io)" on any stream, if the intent is to immediately get the side-effect?

    Your quoted specification is a beast, with many ambiguous terms like "as soon as possible" -- that is not specific enough for programming. In any case, can we can ignore that ambiguous specification and simply call flush() after a series of print()s, and get the intended behavior?

    But hey, buffered I/O is an optimization... a leaky abstraction, that requires experience to properly understand.. That C spec does nothing to illuminate anyone, at all.
    "stderr is mapped to stdout"? Talk about ambigous terminology! That's just idiotic. They have nothing to do with each other and are totally separate. You have a deep misconception there.

    I don't see how "as soon as possible" is ambigous. How could it appear sooner than possible? And just because your reading comprehension is substandard doesn't mean the standard is useless.

    And, no, I don't agree that you need to flush the standard error stream.

    I'm sorry I bothered responding to you at all. It won't happen again.

  8. #8
    Registered User MacNilly's Avatar
    Join Date
    Oct 2005
    Location
    CA, USA
    Posts
    466
    I don't see how "as soon as possible" is ambigous.
    If I owed you money, and I told you I'd pay you back "as soon as possible", would you think I was being ambiguous?

    I don't think it is ambiguous to say that, since data written to stderr appears on the same terminal as stdout, that stderr is mapped onto stdout, by default.

    I'll set the insults aside, cause I probably came off as an ass anyways.

  9. #9
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    I don't think it is ambiguous to say that, since data written to stderr appears on the same terminal as stdout, that stderr is mapped onto stdout, by default.
    But it is. The stderr stream and the stdout stream may be directed to the console but they are totally separate streams. Also "by default" only applies to systems that have a console.

    If I owed you money, and I told you I'd pay you back "as soon as possible", would you think I was being ambiguous?
    Yes. With wording like that I would be surprised to see the money ever returned without sending in the bone crushers, or perhaps talking to your mother.

    Jim

  10. #10
    Registered User
    Join Date
    May 2012
    Posts
    505
    No, you shouldn't normally need to flush printf() or fprintf().
    fclose() will flush fprintf(), but be aware that fclose() may fail. fprintf(stderr, fmt, ...) is supposedly unbuffered. Nowadays that doesn't always mean it will literally write pixels to the console before returning, but flushing probably won't have an effect.

    The only real case for flushing is when you want to printf() a prompt and have user enter characters on the same line.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  11. #11
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    The difference between stdout and stderr is most obvious when you run your program from the shell. Suppose your program reads from stdin and writes to stdout. Then you would probably use your program from the shell like this:

    do_something <oldmast.dat >newmast.dat

    Everything that your program "printf"'s would go to the stdout, which is now connected to newmast.dat. Notice with this style, you don't need to include any code in your program which opens the file "newmast.dat" and you don't need to make special provisions to let the user write to a different file. But what happens if you want to print an error message, e.g. "Input in incorrect format.". If you printed it in the normal way, it would "disappear" into the newmast.dat file, which is probably not what you want. Printing error messages to stderr is the way to solve this problem, so it is more or less standard to print error messages in that way for UNIX-style programs.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. basic printf and fprintf
    By CASHOUT in forum C Programming
    Replies: 7
    Last Post: 04-20-2013, 04:40 PM
  2. fprintf and printf ?
    By vsovereign in forum C Programming
    Replies: 7
    Last Post: 03-01-2010, 01:13 AM
  3. fprintf vs printf
    By Tiago in forum C Programming
    Replies: 2
    Last Post: 12-12-2009, 01:03 PM
  4. Replies: 7
    Last Post: 03-26-2008, 03:21 AM
  5. printf /fprintf with __int64
    By stormbringer in forum C Programming
    Replies: 1
    Last Post: 11-12-2002, 07:56 AM

Tags for this Thread