Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!uflorida!novavax!twwells!bill From: bill@twwells.com (T. William Wells) Newsgroups: comp.lang.c Subject: Re: Discarded Function Values (To Cast or Not to Cast) Message-ID: <1989Dec7.165802.9099@twwells.com> Date: 7 Dec 89 16:58:02 GMT References: <316@voa3.UUCP> <1989Nov17.154621.2698@aqdata.uucp> <1989Nov18.062322.12728@twwells.com> <11644@smoke.BRL.MIL> <1989Nov19.171815.17445@twwells.com> <20882@mimsy.umd.edu> <1989Nov23.233403.2841@twwells.com> <11680@smoke.BRL.MIL> Organization: None, Ft. Lauderdale, FL Lines: 91 In article <11680@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes: : In article <1989Nov23.233403.2841@twwells.com> bill@twwells.com (T. William Wells) writes: : >function returns value which is always ignored : > fprintf umask putenv : > setgid setuid time : > signal strcpy unlink : > fflush printf sprintf : > strcat sleep fputs : >(The sum total of lint warnings from a program *under : >development*. I can tell you why *each* of these is there. And I : >can tell you, also, which I'm not going to get rid of in the : >production version.) : : Anybody maintaining this code will have to determine why EACH warning : occurs and whether or not it represents a potential problem. For : example, when *printf() and fflush() report errors, is it really safe : to not detect that? In most production applications, it would be a : serious mistake to ignore an output error. In this case, each output function is either an output to stderr, debugging output, or later checked with ferror. There are similar reasons for most of the other functions. The ones where some reason does not exist will eventually go away. The primary reason that I ignore the function return value messages is that I believe that adding the extra casts detracts from readability. Between that, and the minor irritation of putting in all the casts, I decided that, in many cases, it is not worth it to eliminate those messages. It is also worth noting that, for example, casting the one sleep call (in this bit of code) to void does not mean that the reader of the code is spared the necessity of figuring out why the result of the sleep is not used. For that, a comment is necessary. In which case, the cast becomes redundant. (And actually, in this case, the comment isn't even necessary. I'm just using it in a busy loop [argh!] and that a shortened delay is mostly harmless is obvious.) The best argument I've heard for always eliminating them is that, if someone has to add a use of a function in this list, he needs to be more careful about what he does with return values than he would otherwise. (I.e., he can't rely on lint catching him if he forgets to use a return value he should have.) The other argument, that these messages might indicate a problem in the code, I find less valuable. This is because I always do code reviews. When I do a code review, I have to check just as carefully a cast function as I do one whose return value is ignored. Accordingly, the cast does not make my job easier. The person who would benefit is someone who has to take my code and figure out what I've done. Adding the cast would tell him that *I* think that the function result should be ignored; I don't know about you, but when I see such in other's code, I tend to not take their word for it unless the reasons are obvious, in which case the cast doesn't help much. It is a trade-off. I'm on the side of permitting a short list of these functions. I wouldn't have a conniption if I were required to eliminate them all, but I don't see a compelling reason to. : Your code may be perfectly okay, but from years of experience : maintaining UNIX system code written by other people, I've found : that I cannot afford to ignore such "lint" warnings. If, on the : other hand, I've taken the trouble to completely inspect and de-lint : a chunk of software, then at any future date when "lint" shows up in : it I know there is a real problem. In the long run it saves me time. Generally this is true. I make only two exceptions to the rule. The first is for the function return value which is never used, the second is for things that it is difficult or wrong to make lint shut up about. (For that latter, consider bugs in lint.) I'm ambivalent on what to do with things that take #ifdef lint to make lint shut up. Doing it for malloc is one thing, one can arrange that all the checking that should be done gets done. But using #ifdef lint just to eliminate a bit of code that lint won't otherwise shut up about strikes me as dangerous. On the flip side, leaving around random lint warnings isn't good either. But the only solution seems to be to recode, often in ways that causes other problems. : P.S. I don't think you should take counterarguments so personally. : As I said, if your approach works for you, more power to you. Mine : certainly works better for me. If it had been a counterargument, I wouldn't have taken it personally. I'm sick up to here with ad hominems where arguments belong. Hence my nasty response to him. --- Bill { uunet | novavax | ankh | sunvice } !twwells!bill bill@twwells.com