Safe Coding Practices – putchar() as a Loop Condition

It’s not unsafe to use putchar() as condition inside a while loop. If you dare try it, however, you must ensure that it checks for file errors. That’s an area where my own code often falls short.

From last week’s Lesson, I demonstrated various safe coding practices for the getchar() and putchar() functions, most of which deal with the int value returned from each function.

Here is what I’m often guilty of doing in a while loop (though this condition could also wiggle into a for loop as well):

#include <stdio.h>

int main()
{
    char hello[] = "Greetings, Human!\n";
    char *s;

    s = hello;
    while(putchar(*s++))
        ;

    return(0);
}

Pointer s references the string hello, which is output one character at a time as the while loop’s condition.

Most often I use the statement while(putchar(*s++)); as a demonstration of how C can be scrunched up or obfuscated. It’s a common example. The code expands to something more readable:

    s = hello;
    while( *s != '\0' )
    {
        putchar(*s);
        s++;
    }

In my books and courses, I explain that *s!='\0' isn’t necessary because when *s evaluates to the null character, the condition is interpreted as FALSE. Further you can combine the loop’s statements to putchar(*s++), then one thing becomes another, and soon the entire loop is its own condition.

The *s!='\0' condition isn’t enough, however. That’s because putchar() returns an int value, which can also be the EOF or a file error. The following update to the code accounts for these conditions:

#include <stdio.h>
  
int main()
{
    char hello[] = "Greetings, Human!\n";
    char *s;
    int out;

    s = hello;
    while( *s != '\0' )
    {
        out = putchar(*s);
        if( out==EOF || ferror(stdout) )
        {
            puts("\nFile error");
            clearerr(stdout);
            return(1);
        }
        s++;
    }

    return(0);
}

To avoid having to cram too much into the while loop’s condition, I placed the putchar() statement into the loop itself. The value returned is saved in the out variable. That return value is compared with the EOF, along with the ferror() value on the standard output device. When either situation occurs, an error message is displayed, the standard output device cleared of errors, and the program stops.

This version of code is safer than the original because it handles any potential error output. (For details on handling file errors refer to this post.) A problem I had with simulating such errors is that the shell catches most of them before the code has a chance to screw up. Still, if a file became corrupt after output redirection or some other disaster took place, the code would neatly exit, which is the entire point of safe coding practices.

2 thoughts on “Safe Coding Practices – putchar() as a Loop Condition

  1. “Most often I use the statement while(putchar(*s++)); as a demonstration of how C can be scrunched up or obfuscated.”

    This sort of thing used to be a big part of C’s culture. There were even competitions to see who could reduce a bit of code the most (and to make it the most incomprehensible!)

    I suppose there was at one time some practical justification for making code as small and efficient as possible, but taking it to extremes just made it more difficult to understand, change and debug. Also, it didn’t do the language’s reputation any good, and was probably more to do with programmers showing off than actually doing anything worthwhile.

  2. I fully agree.

    It’s been a while since I’ve seen an Obfuscated C contest. Back in the day, they were something to behold. And on a positive note, C’s disdain for formatted code probably spurred on languages such as Python and Swift, where formatting is a part of the syntax.

Leave a Reply