2/8/2026 at 7:18:40 PM
> 1. Explicitly set the C standard to C17 or older, so the code is built using the custom boolean type.> Option 1) seemed like the easiest one, but it also felt a bit like kicking the can down the road – plus, it introduced the question of which standard to use.
Arguably, that's the sanest one: you can't expect the old C code to follow the rules of the new versions of the language. In a better world, each source file would start with something like
#pragma lang_ver stdc89
and it would automatically kick off the compatibility mode in the newer compilers, but oh well. Even modern languages such as Go miss this obvious solution.On the topic of the article, yeah, sticking anything other than 0 or 1 into C99 bool type is UB. Use ints.
by Joker_vD
2/8/2026 at 8:51:56 PM
Yeah, it’s only kicking the can down the road if you’re the actual maintainer of the software.If you’re just a packager, it’s your job to get the package to build and work correctly; for your own sanity, you should be making minimal changes to the underlying code to facilitate that. Get it building with the old language version and file a bug report.
by wk_end
2/8/2026 at 7:35:25 PM
Rust does the right thing, with the per-crate edition =
statement.
by Tuna-Fish
2/9/2026 at 1:20:31 PM
With C you put that information as a build option in your Makefile or similar. That’s a consequence of C only standardizing the actual language (and a runtime library), not the build environment.by layer8
2/8/2026 at 11:35:22 PM
Since you mention Go, it does offer precisely the feature you describe in the form of build constraints. A file starting with //go:build go1.18
tells the toolchain to use Go 1.18. A slightly different syntax was used prior to Go 1.17 but the feature itself has existed since Go 1.0.
by netburst
2/13/2026 at 8:00:10 PM
You also have the directive in go.mod which sets this for the entire module, which is very similar to the Rust edition approach, but each Go version is a small "edition".by fl0ki
2/9/2026 at 2:48:18 PM
I know this is likely to be an unpopular take but: I wish it was normal to ship your compiler in your source repo.Modern compilers are bloated as hell huge things which makes it a bit impractical, but if it was a normal thing to do then we'd probably have optimized the binary sizes somewhat.
I just really like the idea of including _everything_ you need for the project. Also ensures that weird problems like this dont happen. As an extra benefit, if you included the compiler source and a bootstrapping path instead of just the latest binary, then you could easily include project specific compiler / language extensions with no extra effort.
by wheybags
2/9/2026 at 5:34:58 PM
That's pretty close to the underlying concept behind Guix and Nix. Give them a glance, if you can!by alt187
2/8/2026 at 8:54:42 PM
> you can't expect the old C code to follow the rules of the new versions of the languageWell, to be pedantic, the entire point of the C standard, and the standard body, is that you should expect it to work, as long as you're working within the standard!
by nomel
2/8/2026 at 10:17:58 PM
Not really, no. Newer versions of standard can (and do, although rarely, I have give it to C standard committee) introduce incompatibilities with earlier versions of standard. E.g. at one point the standard explicitly allowed to #undef "bool", "true", and "false" (and to redefine them later) but IIRC this has been deprecated and removed.In any case: blindly switching what is essentially a typedef-ed int into _Bool has no business working as expected, since _Bool is a rather quirky type.
by Joker_vD
2/8/2026 at 10:35:47 PM
I'm using the dictionary definition of expect here, which is compatible with what you're saying.by nomel