back
177 comments
> legacy choices when we quite literally were just not smart enough to be making permanent decisions like this

Unnecessary hubris. I assure you the original ABI authors were plenty smart and just faced a different set of problems.

> Our forebears are either not interested in a world without the mounting, crushing debt or just prefer not to tackle that mess right now

The article mentions the organizational/social part of this problem, but then goes on to drop this turd.

I can also assure you that our forebears were neither malicious or lazy; but faced the same problem this proposal does.

I don’t like seeing such disrespect for the folks who laid out the groundwork for us.

They faced much slower computers with very limited memory. They couldn't afford the tricks that today are minimal cost.
There's plenty of direct evidence of preferring not to tackle the mess right now. What makes you think that claim is a turd?

You're taking the idea of respect too far.

The famous C dilemma: we want to be as close to the machine as possible, but don't want to change anything when the machine changes
Because contrary to urban myths, C is a normal high level language like everything else.

The Assembly like abilities have been growing as language extensions in specific compilers, not as part of ISO C.

Going back to K&R C, inline Assembly or intrisics were not even available, all of that required using the Assembler directly.

It really hasn't much to do with C (e.g. there is no such thing as a "C ABI", and especially no such thing as a "standardized C ABI" - not sure if that's even a hot-take anymore).

ABIs are defined by CPU and operating system vendors. Those ABIs usually happen to be quite 'C friendly', but that's not a requirement (for instance the AmigaOS ABI was primarily meant to be used from handwritten assembly code, and Amiga C compilers had to adapt to those ABI rules or they wouldn't be able to call into the operating system DLLs).

No-one cares anymore about ancient computers or weird specialist systems of course, but don't neglect my important requirements by breaking compatibility with any the platforms I am relying on at any point in time. We also need all of the most aggressive optimisations that compiler writers can come up with—this is high-performance code, after all!—but we certainly don't have time to deal with any breaking changes that would force revisions to our big important codebases. Make sure we can realise significant performance gains with just a simple recompilation. But remember to keep everything straightforward and close to the machine: we really hate all that weird UB which it's so easy to trigger by making an obvious, reasonable assumption which turns out to be wrong for some inexplicable reason.
Except for the basic integer types. Change those as much as possible. Hell, CHAR_BIT=12 just to keep them on their toes.

Personal pet theory: C is portable as in "you can retarget the compiler to any machine" moreso than "your code will run on any machine".

so what they gonna do ??
But the industry ultimately runs on compatibility, so I get why they do it. But if compatibility breaks, wouldn't hardware vendors die out? If you look at PLC and other hardware manufacturers, they're not even using modern coding. They're still running on old code. They say it's 'safe and certified code,' but in reality, it's just legacy code.

Because in hardware, programmers, aside from researchers, are often paid much less and work in worse conditions compared to their software counterparts. At a software company, code is the product itself. But in manufacturing, software is treated as a cost attached to machines worth billions of dollars. While equipment and sensors keep getting updated and more expensive, the people connecting everything are seen as a cost cutting target. So hardware programmers generally have good job security, but their salaries aren't high. In that situation, asking them to learn something new instead of sticking with the old ways usually gets resistance, because they're not being properly compensated for that learning

> In that situation, asking them to learn something new instead of sticking with the old ways usually gets resistance, because they're not being properly compensated for that learning

And on top of that... these things are battle tested, often running machinery that isn't just worth millions of dollars but runs goods worth orders of magnitude more. Stuff breaking because some new shiny thing has been introduced... no one bats too much an eye when Reddit's UI is missing a widget here and there because someone pushed vibecoded garbage to prod again, but a car manufacturing line? A chemical plant that needs to operate 24/7 so that nothing solidifies in pipes, wrecking the entire facility to the point you need to fully dismantle it?

When this kind of consequences are in the air, everyone is much much more conservative, because no one wants to be left holding that bag.

> They say it's 'safe and certified code,' but in reality, it's just legacy code.

It's not just legacy code. Some of it is literally certified, that is, it has gone through a certification process. That is a slow and expensive thing to redo; nobody wants to do it for a change that doesn't add real user value.

Thousands of words that boil down to "intmax_t isn't ABI-stable". Who knew? (Everybody.)
I think that's somewhat overly reductive. A significant portion (maybe 1/3-1/2?) of the article is devoted to describing mechanisms by which an ABI could be evolved, including a new (?) mechanism implemented in the author's Clang fork and submitted to the C committee ([0] in the blog post, currently on revision 8 [1]). Sure, it isn't a perfect solution, but as the author says:

> at least we’ll finally have the chance to have that discussion [about breaking ABI] with our communities, rather than just being outright denied the opportunity before Day 0.

[0]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2901.htm

[1]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3913.htm

intmax_t is a dumb idea.

Conceptually intmax_t is a generic type of the form intmax_t<T>. Since C does not have generics, the T is chosen by the compiler during compile time.

But this means that the first time you compile any shared library with an intmax_t parameter or return value in one of its functions, you have permanently baked in the type parameter T to whatever the compiler chose it to be at that moment in time.

You cannot retroactively change intmax_t even if you change the symbols, because intmax_t runs into the same problem any generics system does, you cannot retroactively add instantiations for future types that were not explicitly compiled into the dynamic library.

Even if C gets generics and intmax_t would become obsolete either way, because you don't need intmax_t<T>, you can just have T.

intmax_t is only interesting for choosing the T and even then it is only interesting inside function implementations and never in their signatures.

So my conclusion is that intmax_t was a failed attempt at trying to be "clever" with the idea of introducing generics without introducing generics. This is an idea that is so doomed that anyone trying to rescue it, didn't really understand the problem with intmax_t.

I think the bigger issue is time_t, and I have, in fact wrote comments that literally state the code is "best before Jan 19, 2038." Said code may never be recompiled since it will trigger regulatory certification.
Not really, because many don't even know there isn't such thing as C ABI, rather the OS ABI, when the OS happens to be written in C.
Previous submissions with comments:

- 2023-06-10, 64 points, 16 comments: (https://news.ycombinator.com/item?id=36249253)

- 2022-03-13, 175 points, 129 comments: (https://news.ycombinator.com/item?id=30660528)

The root cause of all C ABI problems are shared libraries. They give so much trouble with little to no benefits. Ideally no application should use them. All dependencies should be compiled from sources with the same compiler and standard library. System libraries aren't needed either, it should be possible to perform syscalls directly. In such approach no ABI incompatibility can happen.

One may say, that shared libraries can save some space for both disk storage and RAM. But such savings aren't that huge and in some cases are even negative - if a library is linked-in, it's possible to discard unused functionality and even inline many library functions.

This has been somewhat argued to death, but even if you put aside operational concerns with static linking (security/size/independent upgradability), many attempts to do away with shared library ABIs end up reinventing them--at least for software whose job it is to integrate with other software on the machine, which is a lot of it.

If you statically link a cryptography stack, you suddenly need a lot more information about what certificate/cipher systems are available on the host via IPC. If you statically link media codecs, you suddenly need a lot more information about hardware acceleration from the host via IPC. If you statically link libraries to manipulate binary data in some shared format, you need extra code to runtime-determine things like endianness. If you're asking hardware to do chunky numerical math, suddenly you need to prepare data with specific widths/sizes and you need to determine that from somewhere.

Windows did good work here with COM, but the average windows app is both more self-contained and targets fewer configurations than a Linux app, so many of those issues don't come up as often as they do on Linux. Linux has a long way to go here, both because there's nothing as capable/ubiquitous as COM there, and because so much Linux software is small and therefore necessarily not self-contained (not talking about the UNIX philosophy and shell tools here--talking more about runtime intermediate layers like VAAPI or compat shims or protocols with multiple implementations).

Should have a (2022) in the title, not that anything has changed (AFAIK), but the sky didn't fall either ;)

In the end, OS/CPU combinations define ABIs, compiler toolchains (no matter what language) can't do much more then follow (if they want to be able to talk to the operating system at least). E.g. if one day operating systems implement stable Rust-friendly ABIs, then C compilers will have to adapt to those conventions instead.

OS and CPU combination define their ABI as "whatever our most popular / default compiler did in 90s". That's the problem with C-based ABIs. OS ABIs aren't independent of the language. So any new language must include a C compiler within for ABI access.

See https://faultlore.com/blah/c-isnt-a-language/ for more detailed analysis.

> // Proposed: Transparent Aliases > _Alias g = f;

I think defining a constant function pointer should work. As long the compiler doesn't store this pointer in the result executable and optimizes-out all calls via it into calls to the source function.

One of the most frustrating things in my opinion about new systems languages, is that they refuse to have a stable ability to, so everything has to pretend to be C at the boundaries.
That's the correct decision.

When Rust chose an unstable ABI it did so for a good reason. I personally think the only place where a stable ABI would be warranted is inside the panic machinery and this is mostly because it is kind of annoying to write perfect no panic Rust just to get rid of the 300KiB overhead but even here I'd take my time, possibly decades, before making the decision to have a stable ABI.

The wrong decision is to choose to support a stable ABI and lock in design mistakes early on.

I'm already hinting at the solution so I'll be taking my leave for now.

I skimmed the article, is this guy actually advocating for planned obsolescence or did I miss something??
He's writing from the perspective of a C and C++ standard contributor, and IIRC esoteric ABI details like this was what he happened to be obsessed with at the time (around 2022) :)
What makes you think the author is "advocating for planned obsolescence"?
Who cares if C dies. If dies then dies do not deserve to more. It means progress.
You must grossly underestimate how much C code is out there. It will be alive (though not necessarily well) after everyone here is gone.
I used to an embedded software engineer, but I did not know this abi thing.
It's quite normal for embedded systems to be built in one go and thus not have to care about ABI

In my opinion, that's the correct thing to do anyhow, even for bigger systems

Yeah, well, that didn't happen
Not yet, at least. There's a paper in the works [0] and it's been continually updated for the past few years so at the very least it doesn't look like this approach has been outright rejected by the committee.

[0]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3913.htm

COM-like C ABI saves C++
Yeah, if you ignore the type libraries and metadata that comes along with it.
Curious. Care to elaborate further?
the ramblings of a madman.
I was battling GCC… until the new guy (a smart business major) pointed out I could just compile from Lua to ASM directly. Claude was happy to write a compiler over night. :facepalm:
Does this relate to the article?

Does it follow the lua spec?

How are tables implemented?

How fast is it compared to normal Lua, luajit interpreter, and luajit jit?

that sounds like a fascinating use case. why were you writing Lua in the first place?
Is C even worth saving at this point? Even standards committee members can't consistently write C code that doesn't overflow and segfault.
> Is C even worth saving

C doesn't need saving, it will continue to survive on its own and even flourish in niches for decades to come. So will "Java"Script. Worse is Better, respectfully, or at least Old and Simple is Tough as F, living long and prosper. See, C doesn't need you but we need C, apparently for the foreseeable future.

Yes, it’s the most useful programming language you can learn.
C will not die but it will simply fade away.

Rust is the new black and it will supplant C/C++ and almost everything else short of virtual machine languages like Java/C#.