Hi Alex, I'm going to drill down to a specific case at issue here because it (1) makes your point, (2) gives me an opportunity to concede something-- turns out it's a hill I have no interest in defending, let alone dying on, and (3) saves me the effort of writing _another_ essay today.
At 2026-02-22T21:45:22+0100, Alejandro Colomar wrote: > Please explain why not. If you do this, everything can be > disambiguated by checking the documentation. If you don't, then it's > not possible, and the reader of the code has to choose between > trusting you or not trusting you. And whenever I read such code, I > tend to think "the programmer seems to be one of those that wants > others to assume it knew what it was doing, but that proves it was > rather dumb, so I'm going to assume everything that programmer did can > be deleted". I'd consider a cast is a sign of what you and I > critisize. It's okay to assume I'm dumb. Plenty of people do. What's puzzling to me is how many of them struggle to provide evidence for their claims despite my offer of plenty. ;-) I write 16 KiB emails _full_ of dumbness, but seldom get quoted compared to how often I'm straw-manned. :-P [much snippage] > BTW, off-topic, but I do have an nprintf() function that is quite > different from that. It calculates the length of the formatted string, Please name it something else. There's already too much confusion around the presence of "n" in string-handling functions (not just in libc, but in curses, too), and it _usually_ indicates the imposition of a limit, not a request for measurement. [much snippage] > You personally. By adding explicit casts, you've stated "I'm aware > that [this function] has a return value, and that I don't need it". > However, now you claim to not have written that code, and thus not > really be in a position to do that claim. It's contradicting > information. That's why I think it would be more prudent to not make > the claim. Now that you cite the specific commit, I see what you're talking about. [much snippage] > While the title mentions printf(3), I really meant printf(3) family, > which is what your commit says; it was an unfortunate and incorrect > abbreviation of the title. Agreed. You copied my bad example from a commit message. > Your commit *does* cover snprintf(3): > > $ git show 4b7a0fe5ab5d | grep snprintf > - snprintf(encoding, sz, "%s-%s", parsed.CharSetRegistry, > + (void) snprintf(encoding, sz, "%s-%s", parsed.CharSetRegistry, Agreed, and that was a mistake. _Every_ other instance in that commit... $ COLUMNS=72 git show --stat 4b7a0fe5ab5d commit 4b7a0fe5ab5d5155bd499cf9506a91a1f4bc0125 Author: G. Branden Robinson <[email protected]> Date: Sat Dec 6 18:26:02 2025 -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`. ChangeLog | 7 +++ src/utils/xtotroff/xtotroff.c | 102 ++++++++++++++++++---------------- 2 files changed, 61 insertions(+), 48 deletions(-) ...was a change to a stdio `FILE`-oriented *printf. I wonder how susceptible LLM-based code generators are to similar mistakes. I don't remember making this decision consciously. Possibly I went into robotic replacement mode. I see so much that I want to improve in groff that I sometimes lull myself into a coal-shoveling stupor. It's not good. When I feel the drudge setting in, I should stop and (a) decompose the problem and/or (b) write a sed script to do the work for me. (b) might actually take longer when tuned to get things _just right_, but can be more challenging and fun. Take away: I need to revisit that change when groff is unfrozen. I don't see a _regression_ here because the return value of `snprintf()` already wasn't being checked. The bug here is that I wrongly annotated it as being _deliberately_ discarded, and that conclusion is not warranted on the available evidence. So let me amend the rule(s) we're arguing about. * I still think it's fine to explicitly cast {f,}printf() return values to void, to document that one doesn't care if output to the stream got truncated. Often, an application is helpless in that scenario anyway. (An analogous situation is: "what can I do if fclose(3) fails?") * Discard of s*printf() functions' return values should, by default, be avoided because they _can_ lead to undesired string truncation and even security problems as a result.[1] _If_ discard is done, it _should_ be with an explicit cast to void _and_ a comment explaining why string truncation is not a hazard or not of consequence. * Another possibility is to not _ever_ discard an s*printf() function's return value, but store it and then immediately use it in an `assert()`, which is better even than a documentary comment. * I'm not sure what's best if some smarmy jerk #defines `NDEBUG`. Regards, Branden [1] https://cwe.mitre.org/data/definitions/222.html
signature.asc
Description: PGP signature
