Hi Branden, On 2026-02-21T21:01:36-0600, G. Branden Robinson wrote: > [stronger-than-usual doses of history, speculation, and opinion follow] > > Hi Alex, > > At 2026-02-21T23:52:08+0100, Alejandro Colomar wrote: > > I'd like to know why you did that. > > > > commit 4b7a0fe5ab5d5155bd499cf9506a91a1f4bc0125 > > Author: G. Branden Robinson <[email protected]> > > Date: 2025-12-06 18:26:02 -0600 > > > > src/utils/xtotroff/xtotroff.c: Fix code style nit. > > > > * src/utils/xtotroff/xtotroff.c: > > (CanonicalizeFontName, FontNamesAmbiguous, MapFont, main): > > Explicitly > > cast unused return values of printf(3)-family functions to `void`. > > > > I've been updating code to remove those casts, because they don't do > > much good. It's essentially just noise. > > I disagree. I feel that one should never call a function with no > evident awareness of its return type. (If its return type is "void", > then no cast should be made!) I acknowledge that type-slovenliness is > a proud tradition in C, but I reject it. It only makes life harder for > medium- to large-scale projects.
Isn't "I don't read the return value" an proof of evident awareness that either a) a function has no return value or b) it has a value we don't care about? Why would it be important to differentiate those two? And even more importantly, when a mistake is made, how do we differentiate a) the programmer know more than us and knew it could discard the value vs b) the programmer was clueless and dumbly dumped the value? > > Languages like Pascal and Ada distinguish "procedures" (which affect the > state of the system only via "side effects") from "functions" that might > be "pure", but even if not, generally communicate information back to > their callers via return values. We have something close in C: __attribute__((__unsequenced__)). It has issues, though, as it's too easy to misuse that attribute, since the compiler will blindly trust anything you say. [...] > No proud C hacker ever lets correctness > get in the way of performance.) I am a proud C hacker, and I am proud to put correctness before performance. :) > Of course historically, C functions returned ints by default even > without declaration because C is descended from the "typeless" B.[0] > And if nobody could think of anything _good_ to stick into the return > value, well then they'd come up with something crappy and return > that.[1] This convention persisted even for functions that returned > pointers. Don't think too hard about what the best datum to return is, > just return _something_--like one of the arguments the caller already > knows because they passed it in. > > https://www.symas.com/post/the-sad-state-of-c-strings > https://dgtalhaven.wordpress.com/2020/05/15/schlemiel-the-painters-algorithm/ In some cases, returning the input pointer is actually useful. I use the return value of memcpy(3) and strcpy(3) to construct interesting one-liner macros. Without that return value, it would be impossible. #define strndupa(s, n) strncat(strcpy(alloca(n + 1), ""), s, n) You might complain that this is inefficient (and indeed, you have a link to Schlemiel the Painer above). However, I'm proud to prefer correctness over performance here. > My explicit discards of the return value remind the reader (often > myself) that, yes, I'm aware that printf() has a return value, and that > I don't need it. Are you sure? I've seen snprintf(3) calls where you've discarded the return value. Should we conclude that you don't care about truncation? That's usually a quite bad bug. What if some you thought the buffer size would be enough but your calculation was wrong? If you had added error handling, you'd catch the bug pretty quickly. Alternatively, if you had used sprintf(3) and _FORTIFY_SOURCE, you'd also catch the bug pretty quickly. However, silent truncation will result in the bug surviving ages. > > "But what if everybody did that? You'd clutter the world with void > typecasts!" > > Yes, if I persist in using crappy APIs. Are you saying snprintf(3) is a crappy API (and I do say that, FWIW, but for other reasons)? Returning a value is quite necessary. > Because the printf() family of > functions have such generally unwanted and useless return values, we > might have to admit to ourselves that K&R's flagship example of "hello, > world!" had several things wrong with it, and that's blasphemy to C > advocates. > > I am not a C advocate. > > If I ever get more experience with Ada, I'm sure I'll have complaints > about it, too. (Actually I have one already, which is that object > declarations aren't "constant" by default, whereas they should have to > be explicitly declared mutable. (Rust gets this right.) Granted, the > utility of that practice was arguably harder to foresee in the largely > uniprocessor 1970s, but on the other hand, even Ada 83 had "tasking", > which already confronted several concurrency problems. Needless to say > all the cool guys decided that was crap--except for Nerain Gehani,[3] > who does not seem to be remembered (fondly? or at all?)--and decided > concurrency wasn't one of C's core competencies, and shouldn't become > one. But don't take my word for it. FWIW, most C programs are still single-threaded today. Let the shell combine them. [...] > The standard C library was, and is, deserving of sterner scrutiny than > it gets--and now that I mention it, gets() was far from the only > grievous wart it has carried. We have paid in confusion, wasted time, > and unclear practices, and will continue to do so, unless we slaughter > sacred cows and reconsider popular idioms from first principles. I'm working on that. :) Have a lovely day! Alex > > You did ask. ;-) > > Regards, > Branden [...] -- <https://www.alejandro-colomar.es>
signature.asc
Description: PGP signature
