Search code examples
cprintfputs

Why does the revised version of the “Hello, world!” program from the book Effective C works using `printf`?


I've embarked on learning to program in C. I've started reading Seacord's Effective C book, and I've got confused already on page 6=D
Earlier in the book, there is this little program which he calls the revised version of the "Hello, world!" program:

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    if (puts("Hello, world!") == EOF) {
        return EXIT_FAILURE;
        // code here never executes
    }
    return EXIT_SUCCESS;
    // code here never executes
}

It works for me as expected. Then Seacord introduces the printf function in a section ending with the following paragraph:

The simplest way to output a string is to use the puts function, as previously shown. If you do use printf instead of puts in the revised version of the “Hello, world!” program, you’ll find it no longer works, because the printf function returns status differently than the puts function. The printf function returns the number of characters printed if it’s successful, or a negative value if an output or encoding error occurred. You can try modifying the “Hello, world!” program to use the printf function as an exercise.

This was already confusing just after reading because earlier he writes:

The puts function returns the value of the macro EOF (a negative integer) if a write error occurs; otherwise, it returns a nonnegative integer value.

Based on these passages, I can't see a relevant difference between the functions' return statuses. Anyway, I tried this program:

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    if (printf("%s\n", "Hello, world!") == EOF) {
        return EXIT_FAILURE;
        // code here never executes
    }
    return EXIT_SUCCESS;
    // code here never executes
}

And it worked. I've also tried multiple compilers and versions on https://godbolt.org/, and it worked every time, although I'm fairly inexperienced yet to use this tool, I think.
My question is: what shouldn't work in this example?

On my computer I use

  • Windows 10 Home 10.0.19045 build 19045
  • Microsoft Visual Studio Community 2022 (64-bit) Version 17.5.1
  • Microsoft Visual C++ 2022 00482-90000-00000-AA637
  • Microsoft C/C++ Optimizing Compiler Version 19.35.32215 for x64

I used the following command in the x64 Native Tools Command Prompt for VS 2022:
cl /std:c17 filename.c

(I apologise for writing so many details, but I don't know yet what's important for you. I welcome any advice on what information to provide in future questions.)


Solution

  • The difference is that the function puts returns EOF in case of an error while the function printf returns a negative value (not necessary equal to EOF) in case of an error.

    From the C Standard (7.21.7.9 The puts function)

    3 The puts function returns EOF if a write error occurs; otherwise it returns a nonnegative value.

    and (7.21.6.3 The printf function)

    3 The printf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred.

    So this condition for a call of printf

    if (printf("%s\n", "Hello, world!") == EOF)
    

    can evaluate to false even if an error occurred.

    For printf you should write

    if (printf("%s\n", "Hello, world!") < 0 )