When does void make code less readable?

Henry Spencer henry at utzoo.UUCP
Sat Feb 23 02:32:19 AEST 1985


>  |In general, void is A Good Thing.  C routines that return a value
>  |are like Pascal functions, while C routines not returning values
>  |are like Pascal procedures, and should be declared as void to keep
>  |things clear.
> I thought that just using `return' instead of `return ( expression )'
> told lint that the function wasn't returning a value, and hence
> the returned value could be ignored. VOID tells lint that a
> value is returned but it is ignored. Please correct me if I am wrong!

There are two different uses of void here:  using it to declare that
a function returns no value (to the compiler and to human beings, not
just to lint), and using it in a cast to throw away an unwanted return
value.  The former is presumably what Bill is referring to.

>  |However, some system/library routines, such as close(),
>  |fclose(), and free() return values that programs don't usually care
>  |about.  If the system is unable to close a file, you've got problems
>  |that a normal program can't deal with anyway. 

Actually, note that the asynchronous nature of Unix disk i/o can cause
a real, live i/o error to be reported to a close() rather than to the
write() that caused it.  Programs which really want to be paranoid *will*
check the returned value from close() and fclose().

The basic problem here is that most programs want to see an error-free
i/o system abstraction, but a few want to know about problems.  Splitting
these two levels would simplify this problem immensely, but it's a bit
late for that now.

> I agree. I think it would be a useful thing for routines that normally
> "can't" fail, or return values that are ignored 90% of the time, to
> provide instead a general `event' handling function...

I am deeply suspicious of event-handling primitives; I don't think I
have ever seen a good way of doing them.  Lots of bad ways, though.
One thing which *can* be very handy is variants of the standard routines
which are "guaranteed" to work because they abort the program if the
standard routine underneath returned an error.  The K&P efopen() is a
prime example.  We also now have an emalloc(), which is an enormous
convenience since there is very seldom anything useful to do when malloc
fails.  (Incidentally, a global s/malloc/emalloc/ is an excellent way
of improving the robustness of 4.2BSD code.)  Although this sort of
thing can't be incorporated into old code just by recompiling, in new
code it's much simpler than introducing pseudo-signals and hence
asynchronism and all the nightmares that involves.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry



More information about the Comp.lang.c mailing list