xorl %eax, %eax

Casting printf to void

with one comment

On various projects and specifically on OpenBSD you can see that every single call to printf(3) is casted to void. I found this a really good practice for production code. As you already know from Silvio’s post a few months ago, printf(3) can fail and if you want 100% robust and secure code you should check its return value. But since this is kind of infrequent situation, most developers choose to perform calls like this:

sh-3.1$ cat lame.c
#include <stdio.h>

int
main(void)
{
printf("test msg\n");
return 0;
}

sh-3.1$ gcc lame.c -o lame && ./lame
test msg
sh-3.1$

Of course using this convention, it’s really hard to notice that there is a return value on printf(3) at a large source code file. OpenBSD as well as other projects use the following convention for printf(3) calls:

sh-3.1$ cat not_so_lame.c
#include <stdio.h>

int
main(void)
{
(void)printf("test msg\n");
return 0;
}

sh-3.1$ gcc not_so_lame.c -o not_so_lame && ./not_so_lame
test msg
sh-3.1$

Here we have a cast to void. Of course this mean that there is no longer a return value since it is casted to void but in addition it is much more easier to think that there is a return value when reading large source code files because of this simple cast. Of course, both of these conventions are insecure and do not deal with the case that Silvio described. Normally, calls to printf(3) should be performed like this:

sh-3.1$ cat cool.c
#include <stdio.h>

int
main(void)
{
while (printf("test msg\n") > 0);
return 0;
}

sh-3.1$ gcc cool.c -o cool && ./cool
test msg
sh-3.1$

Here, if an error occurs (which means the disk is full) and printf(3) fails, it will return a negative value. So, we keep executing it until we have some space freed and thus print the message. In the previous conventions you’ll never know whether a call failed or not but using simple structures like the one I used on cool.c you can ensure that the message will be printed. Additionally, you can have similar if statements to free some space if a printf call fails or just free some space inside the while loop.

Written by xorl

January 21, 2009 at 18:23

Posted in C programming

One Response

Subscribe to comments with RSS.

  1. Disk full isn’t the only error you can get, and busy waiting hoping the disk will become unfull, or other error conditions will clear up is probably not the best solution. Also, printf returns the number of characters output, so it can fail to complete its job while still returning something larger than zero.

    Stdout could have been closed, or connected to a socket that has been disconnected, for example, in which case now you’ve got a an infinite busy wait.

    The casting to void that you’ve seen is probably done mainly so that lint or similar tools don’t complain about it, rather than to remind anyone that printf returns a value.

    scaryreasoner

    March 5, 2009 at 05:33


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s