15 ms·
C isn't a programming language anymore
- hardware2win 4y agoWeb is eating world We use it for crossplatform dev. We use json as data exchange format everywhere We will run our apps in webassembly based sandboxes So how about using this mature techstack to talk to OSes too?
- lolinder 4y agoPlenty of people do--it's called Electron. The problem C and friends solve is "how do you write the web or the OS?" You can't bootstrap an interpreted language like JavaScript or even WebAssembly, the VM has to be written in something.
- efficax 4y agoand in fact the VM pretty much has to be written in C (or C++, or you could get away with unsafe rust) since efficient function dispatch (not to mention JIT) are difficult without wildeyed pointer manipulation (you want to emit instructions to somewhere in memory and then jump to them, something inherently unsafe)
- lolinder 4y ago> you want to emit instructions to somewhere in memory and then jump to them, something inherently unsafe Isn't this only for JIT? My understanding was that non-JIT VMs basically function as emulators of a non-existent CPU, so they interpret each bytecode instruction rather than asking the CPU proper to do a jump.
- efficax 4y agoeven a bytecode vm has to emit bytecode and then move an instruction pointer around. You can do it without using C pointer manipulation but it will always be less than ideal. This is a nice little blog post about it: https://pliniker.github.io/post/dispatchers/ https://pliniker.github.io/post/dispatchers/
- lolinder 4y agoThanks! I'm starting work on a VM right now for a side project and was seriously considering using Rust, so this will be really helpful!
- an-unknown 4y ago> and in fact the VM pretty much has to be written in C What makes you think that you need C/C++ for this? Compilers were and still are written in many languages, and you can always come up with a compiler written in an "arbitrary" language which outputs e.g. an executable ELF file containing your VM runtime code. There are a few examples of this in the wild btw, look at e.g. the GraalVM and its SubstrateVM sub-project.
- efficax 4y agoI'm not familiar with the way GraalVM is implemented but I do know that at some point it has to have access to raw memory and registers in order to do JIT. There's no getting around that (and you can't do that with just java). A compiler is different from a JIT engine since yeah you can just write whatever binary you want to disk, hell you could write an x86 compiler in javascript. but if you want to emit instructions to memory and send the CPU there to consume them, you need a smidge of native code.
- pjmlp 4y agoYes you can, that is what compiler intrisics are for. https://chrisseaton.com/truffleruby/jokerconf17/ https://chrisseaton.com/truffleruby/jokerconf17/
- dahfizz 4y agoSomeone actually has to implement the web browser / "tech stack". Web assembly, despite it's name, is an interpreted language. It is not magic. Interpreted languages need an interpreter (written in C).
- hardware2win 4y agoWhy written in C? If C is just wrapper over asm Then emit it from any other lang
- dahfizz 4y agoBecause, as the article states, the OS interface is C. In order to do anything useful at all in your code, you need to call through the C API of your operating system. To replace this, you would need another compiled language. It can't be "any other lang" - it needs to be something compiled down to machine code that can be directly executed on your CPU. So you could write a new OS that presents an interface in Rust, or Zig, but never WASM.
- pjmlp 4y agoIBM and Unisys mainframes and microcomputers beg to differ, with their language environments.
- lolinder 4y agoI don't think it has to be C, but it can't be any arbitrary language. It has to compile to machine code, and I wouldn't want to implement a VM in a garbage collected language because you need more fine-grained control over memory then those can provide. That last requirement rules out most languages with any significant community besides C/C++, Rust, Zig, and a few other even lower profile C replacements.
- kevin_thibedeau 4y agoBecause that mature stack is burning a lot of cycles converting binary data into text and back.
- DubiousPusher 4y agoIn retrospect, flexible bit-width types were a mistake. I'm not sure in what case you get much benefit by ignoring the domain of your variable.
- anfilt 4y agoIt's not exactly ignored in C itself. That's what things like the sizeof() operator are for and standard macros like INT_MAX and INT_MIN. The problem here is once compiled this information is not readily accessible without being able to read a C Header. That's why the author here mentions parsing a C header and says most people just end up letting a compiler do that. If your writing C and ignoring things like INT_MAX or the minimum range requirements specified by the standard or not using sizeof() when your worried the memory size of these base types. Your code is not going to be portable. C definitely let's you handle and know the domain of your variables.
- nwellnhof 4y agoWell, different architectures have different word sizes. What should strlen return? A 64-bit value on every platform?
- tmtvl 4y agoA 256-bit value on every platform. 256 bits ought to be enough for everyone.
- eterps 4y agoWhat does “talking” C mean? It means getting descriptions of an interface’s types and functions in the form of a C header and somehow: matching the layouts of those types doing some stuff with linkers to resolve the function’s symbols as pointers calling those functions with the appropriate ABI (like putting args in the right registers) Well we’ve got a few problems here: You can’t actually write a C parser. C doesn’t actually have an ABI. Or even defined type layouts. That we have this situation today still surprises me. I mean I know how we ended up here, but it is so unfortunate and has a huge cost.
- klipt 4y agoC is basically portable* assembly which is why it got so popular. * but see the whole linked article for where portability breaks down.
- fargle 4y agoIt's portable assembler in the language and (mostly) semantics, but not system interfacing. Meaning you can just create functions, loops, assign variables, create expressions etc. in a common syntax that spans a wide variety of CPU architectures. You don't have to know the names of registers and what they are used for, whether you have a register-memory machine or or a load/store machine. If you had to write really assembler programs across multiple machines, you'd appreciate how much above assembly C really is for remarkably low performance cost. I agree with you - I think that's a major part of the popularity - it was not the first systems language, nor high(er)-level language. It was the first that was widely portable, widely applicable (vs. FORTRAN), and equal or better performance than native assembly.
- cryptonector 4y agoWe've always had this situation, but when C was the only real systems programming language around we didn't notice it so much. FFIs were always painful, like JNI, and we accepted it. This situation is much more noticeable now that we have Rust, Go, etc. all trying to be completely detached from the C run-time. And it's not just those. Even languages like Java and Python that do use the C run-time, they all want to have nice and easy FFIs nowadays, but it's still hard to do it safely and elegantly.
- deadlast2 4y agoWhat is with all the C hate on hackernews these days. I would love to go back to coding in c. Just once you program in Java it is very hard to be productive in c again.
- post-it 4y agoI love the aesthetic of coding in C. Too bad it sucks.
- deleted 4y ago[deleted]
- chrisseaton 4y agoI also enjoy a bit of green-field coding in C. https://www.humprog.org/~stephen/research/papers/kell17some-preprint.pdf https://www.humprog.org/~stephen/research/papers/kell17some-...
- Hemospectrum 4y agoI don’t see hate here. Just disappointment, from programmers who used to like C and feel like it has let us all down.
- orwin 4y agoI really thought i would disagree with this take (i don't know the author), but in fact, this seems like the most honests anti-C arguments i have ever read. I'm not sure if i agree with the conclusions yet, i do not have the technical knowledge (Correction: i wrote an uninteresting paragraph about some thought i had here while re-reading the article to avoid misquoting and misinterpreting: re-reading convinced me that the author conclusions are right, and my paragraph is now useless. If you have nice counterpoints to the article in the comments, i would love to be wrong).
- jmclnx 4y agoLooks like another c rant. Oh well, back to using c. Now if he was complaining of the move to ANSI c from K&R, then I would listen :)
- cryptonector 4y agoI think we should agree that `intmax_t` was a mistake and not focus on it so much in articles like this. It's enough that the C ABI is so hard to pin down, and that C headers are hard to parse. What we really need to interop w/ C but w/o C is a C compiler based tool that outputs DWARF or DWARF-like debug output that actually lays out everything -- type sizes and layouts down to the individual bits that bitfields map to, enum values, constant-like macros, etc. Function-like macros you'll never really be able to use from other languages, so, oh well. Such debug metadata would have to be encoded in a stable/committed encoding, expressed in a stable schema. With that sort of debug info a language like Rust could take care of all C interop natively w/o C, especially if those debug files were included with the OS so that Rust wouldn't need to invoke the tool that generates them. Though, obviously some `-D...` C compiler/pre-processor arguments can radically change the contents of the parsed headers, so some rationalization would be needed to cut down the number of "ABIs" to a manageable set (like GNU, BSD, POSIX).
- nerdponx 4y ago> C compiler based tool that outputs DWARF or DWARF-like debug output that actually lays out everything That sounds like C2FFI: https://github.com/rpav/c2ffi https://github.com/rpav/c2ffi The only language ecosystem where I've seen it used is Common Lisp, in the CL-Autowrap library (https://github.com/rpav/cl-autowrap https://github.com/rpav/cl-autowrap). But C2FFI emits plain JSON, so I don't see any reason why you couldn't build e.g. a Python auto-binding library on top of it. It depends on LLVM to generate the spec file, but end users don't need to have that.
- trynewideas 4y agoIt also kinda sorta sounds like this tool the author wrote: https://github.com/Gankra/abi-cafe https://github.com/Gankra/abi-cafe > This tool helps automate testing that two languages/compilers agree on ABIs for the purposes of FFI. This is still in early development so lots of stuff is stubbed out. ... > By running this natively on whatever platform you care about, this will tell you what FFI interfaces do and don't currently work. Ideally all you need to do is cargo run, but we're dealing with native toolchains so, expect toolchain bugs!
- cjdrake 4y agoYes, it is.
- isk517 4y agoNo it isn't, advancements in programming science have lead to C being reclassified as a dwarf programming language,
- nerdponx 4y agoWould it be possible to create a binary library format that declares its own ABI? Has anyone done something like that in the recent past? Not like GObject declaring the interface in a special comment (modulo typos). Something that's fully machine-parseable in any programming language and does not require access to the source code. I mentioned C2FFI (https://github.com/rpav/c2ffi https://github.com/rpav/c2ffi) in another post in this thread. That's an extra "spec.json" file that you need to distribute along with your library, but maybe that's a whole lot easier and simpler than inventing a new library format. And it's JSON, which is human-readable, so it's relatively easy to debug.
- pavlov 4y agoMicrosoft COM? It’s the foundation for a lot of the Windows API and was explicitly designed to be usable from non-C languages.
- anfilt 4y agoCOM! Have you ever tried interacting without some automated tooling or language support! It's horrible and verbose. When it comes to setting up everything to interact with COM, I feel likely I would be more productive in assembly. Although at least a lot of it can be setup with automated tooling. Although the interface seems to also have a lot more overhead than a basic function call. I hardly would call it a better situation.
- account42 4y ago
- skybrian 4y agoMaybe someday Zig and/or WebAssembly will evolve some better cross-language ABI?
- dralley 4y agoI seem to recall Patrick Walton and Andrew Kelley having a discussion about that on Twitter.
- choeger 4y agoHmm, I know that C is not parseable, but couldn't one define a parseable subset that is still meaningful? That would then pass the burden to the developers that want to bind to a specific library and hopefully these developers have a clue on how that library builds, works, and what functions are needed. In the long run, if a popular language (say rust) strictly insists on that subset being used, I could imagine that upstream libraries would start shipping such headers, say openssl would not come with a rust interface but a "machine-readable" C interface.
- wvenable 4y agoThis is the solution. It doesn't even need to be parseable subset of C -- it could be anything. It just needs to be able to describe an ABI. And from that, you generate C headers or bindings for other languages. I don't think this idea is in any way controversial -- it would just be a lot of work to do across a large number of systems.
- x128 4y agoWhy base it off C?
- stephc_int13 4y agoThe author is not talking about C but about the C ABI that is the default OS ABI. It's an ABI, there have to be one, and C was the de-facto system programming language. I don't get the complaint, there are flaws, it could have been much MUCH worse.
- wvenable 4y agoThe complaint is that C isn't the only systems language anymore so defining the ABI in terms of executable C code is a pain-in-the-ass for those other languages. C is also a terrible language to define an ABI because, by design, it's very imprecise in the way that it defines types.
- AnIdiotOnTheNet 4y ago> The complaint is that C isn't the only systems language anymore C was never the only systems language.
- pjmlp 4y agoFor a long time on UNIX it definitely was, until it got its sibling CFront in the package.
- akira2501 4y ago> it's very imprecise in the way that it defines types. It's perfectly precise, particularly if you choose to use <stdint.h> which has been available in the language for a very long time. You may have some issues with specific types and platform variability, but it's absurd to cast this as "it's imprecise with types." It's _flexible_ with types. People seem to miss that this is the reason why C is the lingua franca. It isn't trying to "perfect" computing. It just makes it possible. There's a lesson for new languages here.
- unclad5968 4y agoWhat kind of precision would you like to see added to the way C defines types?
- prerok 4y agoI don't really get what the author is driving at. Sure, each system has quirks so designing a portable FFI is difficult to say the least. But what's the alternative? In my experience I have seen plenty of standards violated and downright disregarded because the platform has special functionalities or quirks. My view is that even if there was an ironclad ABI spec platforms would still violate it with their special implementation of the system interface. I think we would end up with exactly the same problems only the rant would not be targetting C but something else.
- anfilt 4y agoThat's my thought as well. It probably would be even worse. For instance it possible to write a leaf function in assembly for AMD64 that runs both on linux and windows if all you do is return a value. This is because they both use RAX as the return register. There subtle difference between the two but that is mainly what registers are used. The biggest difference comes in the stack layout. Now when it comes to pretty much any other OS for instance on x64 they pretty much use the System V calling convention. The thing is if C was not the glue, I could imagine the ABI would be wildly different on each OS heck maybe even each version of the OS. If we look at windows you can't safely call any system calls directly since a major update could change the system call number. However, windows provides wrappers around these system calls. Linux is an outlier in OSes that considers changing system calls like this as breaking user-space. Now if we did not have C what would operating systems be using to wrap all these system calls? I suspect something tailored to that OS specifically and it would be quite the mess so I bet it would even be worse to handle. Since at least C keeps things similar. Whereas without it you would get OS specific schemes that could vary by a lot more! Making the code base to support multiple platforms even larger.
- haberman 4y agoThat was exactly my reaction when this article was last on HN: https://news.ycombinator.com/item?id=30706326 https://news.ycombinator.com/item?id=30706326
- prerok 4y agoThanks for the link. You put it much better than I did :)
- dahfizz 4y ago> Now C isn’t just a programming language, it’s a protocol. Clickbait headline, but an interesting article.
- markhaslam 4y agoPrevious discussion 8 months ago: https://news.ycombinator.com/item?id=30704642 https://news.ycombinator.com/item?id=30704642
- shadowofneptune 4y agoLot of these pain points came up when I was trying to make Pascal bindings for LibBF (https://bellard.org/libbf/ https://bellard.org/libbf/). The only API docimentation it has is the header file itself, and the automatic C-to-Pascal translator choked on something without giving an error message. It's a slow grind to translate everything by hand. One of the things that makes you wish C had proper modules (C++ does, finally).
- pjmlp 4y agoThis is the kind of pain that made me back in the day move from Turbo Pascal to C++, and only use platform languages, as at least the platform owner has teams dedicated to managing bindings to all SDK languages.
- jylam 4y agoI'd say the author, although they are right in most of their arguments, just want C to be a higher level language, well defined, well supported by every OSes out there in the same way. I'd hate to see that happen, and I write C every day, read hundreds of lines of C everyday, and actually formally prove C everyday. C is not meant to be Rust or Go or Java. I'm actually against most of additions those days to the new standard. They complicate things, the (barely) portable assembly it's meant to be. I wouldn't write a database in C today, but I'd be happy to start a new bootloader project in C tomorrow. The author is actually angry that the OSes still expose a C interface when they should use something higher level, like it seems Apple is doing (I may be wrong). I get that, but like we say in France, don't discard the baby with the bath water. The problem is that, as they say clearly, C is the lingua franca. C isn't the problem, its use is.
- anfilt 4y agoOh god Apples platform is a mess!!! I would hate to see more of that. If they think C is bad. Try interacting with for instance objective C at a low level is even worse for functionality provided by the OS.
- intrasight 4y agoThe C Programming Language. Wow - a throwback in time. I learned to program using the 1st (1978) edition. Haven't touch C since 1994. I'll rephrase title as "C Isn't a Programming Language that I use Anymore". But I have great memories of that era of my hacking career.
- bjourne 4y agoThe way out of this mess is services. You don't call the open function through some ABI, instead you send a message to a file system service through a mediator and get a file handle back. On Linux, that mediator would be D-Bus, developed by the GNOME people who relatively early recognized the need for it. Possibly because everything in GNOME is written in C so they were familiar with how painful it is to interact with C libraries. Of course, services aren't panacea and they incur large performance penalties due to the context switching. However, for non-performance critical tasks services are the future.
- IYasha 4y agoDo you realize HOW slow this stuff is? :D :D I shudder when I hear "D-Bus". ) It's a nightmare. I remember being able to destroy Ubuntu just by holding the PrintScreen key for THREE SECONDS which overloaded the DBus to the point the whole system becomes unusable. ) I would definitely NOT want to depend on that. I liked the COM/ActiveX-way, which was fast and somewhat flexible. But proprietary.
- deleted 4y ago[deleted]
- pjmlp 4y agoThe idea behind it is a key component on Apple, Microsoft and Google platforms. They seem to be doing just fine.
- anthk 4y agoFuck that crap. BSD's doesn't need any glib/dbus crapware.
- pjmlp 4y agoThat is how most APIs nowadays work across Apple, Google and Microsoft platforms. XPC, drivers, Android/Fuchsia/ChromeOS IDL, COM, WinRT
- account42 4y agoHow do you send D-Bus messages. That's right, via a C ABI. D-Bus is not about interacting with libraries, it is about inter-process communication.
- deleted 4y ago[deleted]
- dillon 4y agoSquares are not Rectangles anymore! In order for my new and improved Rectangle to talk to another really cool Rectangle, I have to resize one of my edges to fit nicely on the Square and the 2nd Rectangle must do the same. The Square is a stable interface that rarely changes. I hate that the Square is a stable structure that doesn't change sizes dramatically when it's proven that a new size is better. In conclusion, Squares are no longer Rectangles.
- constantcrying 4y agoThe problem the author has is not with the C programming language, no argument here is about some language construct or some abstraction within it, in fact very little about the actual language is said. To me it is very clear that the issues described do not lie with C(++), the programming language, but with C(++), the language which powers everything from a 8-bit micro controller to the most modern super computer and almost every operating system you can try to put on top of them. With any language as ubiquitous as C these issues about types had to arise at some point and the reason that most languages "feel" much more streamlined regarding types, is because they never pretend to care about some obscure niche architecture. The same goes for "C as the language of ABIs", it is a very simplifying choice to have the ABI of your OS be described in the programming language of the kernel. Sure, it does not need to be, but if your language is the layer between software and hardware, maybe it has some right to dictate how you talk to it. Any language which wants to have a comparable feature set to C in terms of breadth of platforms and depth of penetration will run into issues like this. Maybe it can, with the benefit of half a century of hindsight, make better choices.
- agentultra 4y agoA thousand times this. I understand the frustration of principled PL authors trying to bootstrap an ecosystem for programs compiled from their language to run on. It can be frustrating having to interact with foreign memory that you don't control and specifications that intentionally leave much to be desired by allowing the hardware platform to decide the memory layout... But if you didn't have these things it would be a lot harder to get even a basic system going. It would be nice if there were _one_ standard way to encode an sized integer to rule them all... but we don't live in that ideal world. Pick an arbitrary, common layout, and stick with that. Your language might not let users target some micro-controller that runs on a toothbrush but you probably don't need to anyway.
- int_19h 4y agoYou can't pick an arbitrary layout to interop with some C code that uses intmax_t, for example.
- bakugo 4y agoIf Rust fanatics spent as much time writing software in Rust as they do writing rants about how much they hate C and C++, they'd be a lot more productive.
- pessimizer 4y agoYou can't really be making the case that people aren't rewriting everything in Rust enough.
- ridiculous_fish 4y agoI worked on NSInvocation during Apple's 64 bit transition. NSInvocation is an FFI: it allows you to construct calls to ObjC methods given a runtime signature, which means implementing the calling conventions of four platforms (PPC and x86, 32 and 64 bit). My approach was to write a script which generated functions for all possible signatures, up to N parameters. The functions verified the values they were passed both natively and through NSInvocation. This flushed out a huge number of weird, undocumented ABI corner cases. For example on PPC, when returning a struct containing a bitfield, sometimes the bits are aligned at the top (MSB) of the register, other times at the bottom, depending on the width of the bitfield! This was just an old gcc bug, but it can't be fixed without breaking the ABI. The resulting C code was so large it also unearthed a PPC64 compiler bug! PPC jump instructions have a 24-bit immediate offset. If the offset needs to be larger than 24 bits, it's supposed to load the offset into a register and emit an indirect jump. This just didn't work, but nobody noticed, since you'd need to branch past ~33MB of code in a single function to hit it.
- pmarreck 4y ago> If the offset needs to be larger than 24 bits, it's supposed to load the offset into a register and emit an indirect jump imagine unit tests existing for claimed functionalities :: eye roll ::
- mmastrac 4y ago> The resulting C code was so large > you'd need to branch past ~33MB of code in a single function to hit it. That's... an impressive amount of C code.
- ranger_danger 4y agoNot really... many modern desktop applications are >100MB when built statically.
- rowanG077 4y agoThat's binary size. Not code size.
- pmarreck 4y agoIt seems like failing to be strict about defining behavior and expectations under all conceivable circumstances (such as leaving the actual bit length of certain integer types to be "up to the architecture to decide" in order to "remain flexible") is always a long-term design mistake.
- acuozzo 4y agoThe standards committee couldn't deprecate all of the C written prior to 1989 in order to redesign the language. C compilers existed for all kinds of architectures at that time, including CPUs featuring 36-bit (yes, thirty-six bits) words. A lack of flexibility would have resulted in a lack of adoption which would have rendered their work meaningless.
- none_to_remain 4y agoAs far as I know to this day there are DSP platforms where a C char is 32 or 64 bits because that is what the platform can address. There's a macro, CHAR_BIT I think, that you can use to get a bit count if you're attempting to write really portable C
- acuozzo 4y agoExactly. This is the kind of flexibility I was referencing in my reply.
- IYasha 4y agoI like the _MINIDUMP_HANDLE_DESCRIPTOR example. I write like that. And I don't think keeping compatibility in APIs and ABIs is a language thing. It's more what a programmer as an architect of his program does.
- munificent 4y agoI saw Zach Tellman's excellent talk at Papers We Love / Strange Loop this year[1]. In it, he talks about the Ship of Theseus [2] thought experiment as it applies to software. His very insightful observation is that you can replace every plank in the ship one at a time and the resulting ship still looks the same. That's because each time you replace one plank, it must fit with the surrounding existing ones. So while the components are replaced, the interface between them is unchanging. If you believe the result of the thought experience is that it is the same boat, then it's because the set of interfaces define the boat. This applies very much to C as the universal ABI. It's common to see programs written in a combination of languages who interface with each other using a C ABI even though none of those languages is itself C. And, for better worse, it's really hard to change this because while components are easily swapped out, moving an interface is hard because you have to simultaneously fix every component that uses that interface. [1]: https://www.youtube.com/watch?v=tHThXQr7wwA https://www.youtube.com/watch?v=tHThXQr7wwA [2]: https://en.wikipedia.org/wiki/Ship_of_Theseus https://en.wikipedia.org/wiki/Ship_of_Theseus
- simplotek 4y ago> This applies very much to C as the universal ABI. It's common to see programs written in a combination of languages who interface with each other using a C ABI even though none of those languages is itself C. And, for better worse, it's really hard to change this because while components are easily swapped out, moving an interface is hard because you have to simultaneously fix every component that uses that interface. I'd go with the glass half full point of view. This has to do with fixing stuff that ain't broken. This has everything to do with developers not wanting to go the Java route and reinvent the wheel and have to reimplements all basic functionalities under the sun. They just target C in particular or in some cases POSIX and they are up and running in no time, reusing everything under the sun with minimal work.
- sbf501 4y agoThere's a lot in here, but I'll target my primary gripe: I don't think it is at ALL fair to blame ABI designation on C. Platform developers have a choice to use an existing annotation or make the world more complex. Guess what? #2. Also, isn't it disingenous to take a cheap shot at C for not being "parse-able" when the OP's favorite language, Rust, has the same syntatic grey areas? I don't know enough about Rust, but from what I know it should have the same issues called out in the HAL paper OP cites.
- skitter 4y ago> Rust, has the same syntatic grey areas? I don't know enough about Rust, but from what I know it should have the same issues called out in the HAL paper OP cites. Which ones? Afaik in Rust it's always clear whether an identifier belongs to the value or the type (or macro) namespace, for example a variable declaration is `let foo =` or `let foo: Bar =` (possibly with a pattern on the left hand side), parameters & constants being similar. This alone rules out most of them. It also doesn't have if/else branches without braces, nor _Atomic. So yeah, seems odd to claim it's disingenuous.
- basicoperation 4y agoInteresting article, but a shame it had to end with a political attack on England for no reason.
- camdenlock 4y agoThis is the typical mode of expression for these post-human / trans-human types. Aggressive ranting language, extreme emotional volatility, narrow collectivist vision, and very deep technical analysis & know-how. Been this way for decades, at least as long as I’ve been paying attention. It’s a culture.
- salmo 4y agoI think the issue with the footprint here is not wanting to reinvent wheels. In theory, if you scrapped libc and up, you could limit your "speaking C" to the kernel of whatever OS/architecture you're using. Different OS/architecture combos would be more of a nightmare than others, but we cheat off libc for that , except we have to do things to support multiple libc implementations some times. It doesn't solve interop with other languages, because they don't want to reinvent wheels either. In theory, you could scrap it all and go hardware up. Have a nice OS with a well defined message passing interface that any language could interact with. You could even make a libc wrapper on top to address portability. In 20 years, it may have serious adoption. The problem is that the situation is "good enough" that nobody wants to solve it. That applies to most technical debt, and really any other human concern.
- anfilt 4y agoThat message passing comes with a lot of overhead while it might be more generic. Making the already bloated software we use these days even slower does not sound like a better alternative. That would make interacting with OS slower, and probably even more important are things like .DLLs/.SOs. If the dynamic library or heck even a static library your linking against used message passing imagine all the cases where that would be a bad idea. All that overhead just so you can call a function not written in whatever language you happen to be using. ABI's like we have now are a much better for this reason. Also just because one uses message passing does not mean there are no compatibility issues. I think the main issue here is if we reference the article linked. "You Can’t Actually Parse A C Header". To know the size of types and therefore figure out memory layout you need to be able to read a C header. With that information you can construct a lot the ABI for a C function. Aside from some OS specific things like stack layout requirements and hardware/OS specific things like what registers are used for certain parameters of a function ect...
- salmo 4y agoSorry, I don't disagree at all and the message passing was a little tongue in cheek. I was in CS in the 90s, when the dream of a message passing microkernel utopia was so hot. I don't see a way around this complaint other than starting from scratch. If you "fixed" C, you'd have to rebuild all those things underneath you. And the reason we do FFI is to not reinvent some chunk of code. I think you fundamentally run into issues with ABI compatibility regardless of language. You get a step better if you could derive the ABI from the code, but there's always interop issues cross-language. I don't think you can avoid wandering into having to implement the isms of the provider's language. So much baggage just comes from strings. Then you have higher level constructs like making threading/concurrency, memory management, etc. jive. That's even an issue at the API level. I use a ton of libraries that just wrap a C library with a language-idiomatic interface.
- quelsolaar 4y agoThe reason C is so dominate here is not that C is magic, its that its pretty much the only thing that does care about having a stable ABI. When people design C replacements, they rarely understand why C is so successful. ABI stability is extremely important. (This is one of the reasons Linux on the desktop has never taken off outside of OSS because the distros don't maintain a stable common ABI) Any other language could do it, just no one does, because its not sexy or fun.
- CodeArtisan 4y agoThe author doesn't mention POSIX at all despite it being what most operating system interfaces are based on. POSIX describes its interface (types and procedures) with Standard C and specifically requires that a compliant system has a C compiler available. If you want to get rid of C, you will have to get rid of POSIX too or have POSIX use something else. POSIX specification: https://pubs.opengroup.org/onlinepubs/9699919799/ https://pubs.opengroup.org/onlinepubs/9699919799/
- zh3 4y ago>C isn't a programming language anymore It's a perfectly fine programming language. Some of us like working with sharp tools (and sub 1 second compile times for 100kloc programs, and close enough to optimal performance, and actually knowing what's really going on). I do sympathise about the API abstractions; some of them have definitely not weathered well. As for ABI's, I've been constantly amazed how well they've been preserved (kernel folks will understand, e.g. 32-bit userspace with 64-bit kernels just works). What will the API/ABI's look like 40 years down the road? (will any modern language endure like C?).
- fweimer 4y agoI wonder if some of this C ABI hate is related to a design quirk of the LLVM tools: Is it true that every front end targeting LLVM needs to implement the C calling convention mostly on its own, rather than specifying a C function signature at the LLVM IR level (using a different syntax, obviously) and have the target backend translate that into the appropriate instruction sequence for the call?
- taylodl 4y agoThe joke in the C community since the early 80's is that C isn't a high-level language, it's a medium-level language. Others quipped C is a portable assembly language: programmer beware! This was 40 years ago! Let's not pretend we've recently discovered all these problems with C. This has been known for decades. It's also been tolerated for decades because we had nothing more performant we could use and we needed to wring every ounce of performance we could get out of those feeble processors we had available at the time. Unfortunately because we were forced to use C it has an inertia that's kept it going all this time. But there's also a counterforce slowing down C's penetration. Now the last bastion of C is kernels, drivers, and embedded systems (used to be much, much more). Now we're seeing Rust starting to move into these spaces and actually we've been using non-C languages now in the embedded system space for the past 10 years. It's really just kernels and drivers remaining for C. As far as using C as an ABI - I agree, that needs to evolve. I'm not opposed to using an interface specification language created specifically for ABI's. I think that's the way forward.
- deleted 4y ago[deleted]
- bArray 4y agoTrying to replace C with something like Rust, is essentially saying that we should rewrite all kernels in Rust. C is the common language because it talks to the kernel, which talks to the hardware. Forgetting how much would need to be replaced with objectively much slower code, Rust simply cannot do some things. You cannot always make absolute guarantees about memory safety for example when it comes to low-level programming. Sometimes to be fast, you have to make assumptions and take risks. I am currently watching the Veloron game [1] as an example of how larger Rust projects may begin to look. I see something like this [2] and it doesn't look all dissimilar from C, just with a new syntax. Has writing this game eliminated all bugs? Nope [3]. Maybe there are less segfaults and bad memory management, but this was just one class of bugs. [1] https://gitlab.com/veloren/veloren https://gitlab.com/veloren/veloren [2] https://gitlab.com/veloren/veloren/-/blob/master/server/src/connection_handler.rs https://gitlab.com/veloren/veloren/-/blob/master/server/src/... [3] https://gitlab.com/veloren/veloren/-/issues/?sort=closed_desc&state=opened&first_page_size=100 https://gitlab.com/veloren/veloren/-/issues/?sort=closed_des...
- kaba0 4y agoWell, rust (and c++ as well) is that much better than c because it actually allows proper abstractions on a language level. You can’t even write a general purpose vector data structure in c, which doesn’t have an overhead.
- WalterBright 4y ago> You can’t actually write a C parser Actually, you can. I added one to the D compiler, and dubbed it ImportC. With ImportC, in your D code you can write: import stdio; and if there's a stdio.h file, the D compiler will read the .h file, parse it, and present the ABI to it in a D-ish manner to your D code. Here it is: https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cparse.d https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cp... It's so darned useful I expect other languages will do it, too. People were skeptical at first, but it's a solid gold productivity enhancer.
- Hemospectrum 4y ago1. Doesn't the D compiler contain an entire C compiler? Half the point of that section was to say that any C parser is halfway to being a fully functional compiler. That's arguably an exaggeration, but I fail to see how D serves as a counterexample. 2. How does the D compiler handle GCC- and Clang-specific extensions to C?
- WalterBright 4y ago1. Yes, it does, but only the cparse.d file is for C. The rest of the "C" compiler hijacks the D semantic routines, code generator, and optimizer. There's also some custom work to turn #define's into simple declarations. If you just want to parse C, yes, you can just use cparse.d. It's important to note that C cannot be fully parsed without keeping a symbol table, and cparse.d handles that, too. 2. C extensions will always be a problem. ImportC supports the most widely used ones. (Most C extensions are rarely used and can be ignored.)
- pencilguin 4y agoC++ did this, what, 40 years ago? Then V, Zig, now D. I agree, in ten years most compilers and even interpreters will do it.
- WalterBright 4y agoC++ did it the other way around. It added C++ to a C compiler.
- WalterBright 4y ago> C doesn’t actually have an ABI. Or even defined type layouts This isn't the problem it appears to be. D's ImportC adjusts its semantics to match what we call the "associated C compiler", which is the predominant one on the target platform.
- pjmlp 4y agoActually how would it work with lets say, using a D compiler in HP-UX, trying to link against binaries produced by aCC?
- WalterBright 4y agoIf HP-UX was a supported system by D, and aCC is the system compiler for HP-UX, it would be made to work. ImportC already makes adjustments for Microsoft C on Windows, Digital Mars C, and the dialect of C used on the Mac.
- pjmlp 4y agoI see, thanks.
- WalterBright 4y ago> Hey Rust, what’s intmax_t on x64 linux? pub type intmax_t = i64; With D's ImportC: import stdint; // reads stdint.h and all its declarations intmax_t x; // declare x as type intmax_t This is fun!
- bitofhope 4y agoAnyone know any good articles, tutorials or books about ABI design? How did we end up with what we have now, what lessons are there to learn? How would you go about designing a new one from scratch? Would this fall more under operating systems or compilers discipline?
- telendram 4y agoThis guy has no idea what he's talking about. Yet again another click-baity title, followed by an angry rant, the topic of which has nothing to do with C after all (but readers have to go through an impressive amount of noise to deduct that).
- synergy20 4y agoGosh, just checked out Ada briefly, looks _much_ simpler than rust, so, why not just going back to Ada and use it for memory safety? why even Zig is needed to be created? are they NIH syndrome or am I missing something.
- dusted 4y agoA better title is "C isn't just a progamming language anymore" I know the purpose of the article is to shit on C, but the fact that it is the lingua franca _despite_ of it's shortcomings, is more than anything a testament to the versatility of the language, and a proof that it somehow ended up the right abstraction distance between javascript and microcode.. Nobody forbids you from making a language that does not speak C, and write a compiler that generates machine-code that has nothing in common with what would have come out of C source, and an OS that natively support whatever conventions that language has. It's not like hardware requires you to write C for it..
- kaba0 4y agoWell, nobody forbids you, but its akin to speaking Chinese in England without ever trying to even learn a word used there. If you want to do anything useful you ought to use the OS layer sooner or later, which will be predominantly a C ABI/API.
- stonogo 4y agoNone of these problems would affect these people if they didn't insist on making their pet programming languages run on what is essentially a C engine. Rust, like a lot of modern high-level languages, basically compiles to llvm ir and then absconds responsibility, leaving things to the fifty years of engineering involved in getting us to where our compiler backends are. The joke used to be "Java will run anywhere someone writes a JVM in C" but now it's "progamming language will run on whatever target someone wrote for LLVM." Then, having used the C and C++ toolchains to boost themselves into a simulacrum of self-hosting, they immediately decide they don't want to actually implement their preferred abstractions in the operating systems they want to use, so they write huge FFI libraries to take advantage of the massive amounts of library code and OS interfaces that we've spent the past fifty years writing. Finally, having arrived on the scene, decided that everyone else is wrong and they're right, using the bad-and-wrong toolchains to bootstrap their throbbingly correct and superior approach, we're treated to angry rants about how fifty years of engineering is messy and why wasn't some omnipotent project manager in the sky keeping all this in check while the world awaited the arrival of someone smart enough to write us, at last, a good and correct programming language? I totally understand that looking into the spaces where our programming languages and our kernels intersect can lead to anger, dismay, and confusion. They're all living projects who have had to adapt to decades of massive change in the computing world; once the LispM went away all hope was lost for coherence. But whining about it in the context of how it makes this thing you felt like doing slightly more difficult is just petulant noise. Just like open source developers don't owe anyone specific features or bugfixes, the Unix and C ecosystem doesn't owe anyone a rigorous, provably correct ABI. If you're not happy about it, don't use it. If you want to benefit from the decades of work, you have to accept the pitfalls that sprung up over that half-century. The alternative is to do it over, yourself, according to your principles. I desperately wish someone would; the benefit to computing would be incredible. So far, everyone dips a toe in the FFI pool, declares it to be too cold, and then swims around in it regardless.