Microsoft, Apple, Google have the luxury to impose moving away from C on their platforms.
On other platforms you have developers that won't touch any kind of Safe C even at gun point.
I suspect that the move to swift would never have happened without LLVM. And I wouldn’t be surprised if llvm’s cross language compatibility was specifically attractive to Apple because it let them have their cake and eat it too - write a new language but keep legacy C code whenever that’s the best option.
I don't believe LLVM provides a stable cross language ABI, and AFAIK languages just use regular FFI (via the C ABI) to communicate with one another, regardless of them being implemented on LLVM or not.
Provided the compilers generate compatible versions of LLVM IR, then cross-language calls can be done at the IR level. See github.com/Keno/Cxx.jl
IIUC Swift already uses clang to load module maps in order to expose and call Objective-C, and they plan to do something similar with C++ (no link handy but I think there is an issue or enhancement proposal about it).
Is there really such a thing? I thought the ABI was dependent on the operating system and compiler.
I agree that C is unique in it's ability to generate programs that can be interfaced with from any language. This also seems to apply to older languages like Fortran and Pascal, for some reason. Higher level languages are an ABI nightmare; seriously doubt anyone will ever dynamically link against a C++ library at runtime and call a method on a C++ object from any language that isn't C++.
2. Prior to LLVM, there were much more complete attempts at this (that were even more successful, actually!)
A lot of C's endurance is related to programmer psychology, so it would be futile to design a better C.
C++, Rust, Go, Java will continue to drain the pool of C developers until it's only used for maintenance of existing projects.
This is why it's extremely irksome to see people recommend mixing C and e.g. Python for speed, or other such Frankenstein's monsters - it's just prolonging the agony of whoever will maintain that.
Rust, Go, and Java, with their memory management and cross-platform portability, and general non-determinism may eat away at the edge of C, but can never replace it.
I could see them fully replacing C if features like garbage collection and byte-code interpretation were handled at the chip-level, so languages would not have to necessarily deal with them. Could also see it happening if a chip's out-of-order execution was exposed at the language level. That would not necessarily make C worse, but Java may be more adept at handling it.
1. C is no closer than C++, or Rust (including unsafe) and they're all surprisingly pretty far from the hardware these days... this is visible the most in multi-threading, where high-level C statements are re-ordered by the compiler and even simple C statements like an integer assignment can be split into multiple instructions. Inlining and register allocation is also quite opaque and perhaps best left to the compiler, unless one uses non-standard code to force specific behaviour.
2. Well put: Go and Java were/are eating at the edge of C. Java took serious bites in the past, nowadays they're not really competing much. Today, what might have been a small Linux C program could be a Go program, especially if the performance constraints aren't too tight. Technically speaking, Rust can replace C almost everywhere, it's just that it's a significantly more complex language.
C++ introduces virtual functions, and when you make a function call, you're no longer going to a single place in memory, you go to where the class's virtual function table tells you to go, effectively jumping to a memory pointer. This is pretty helpful, but it's an incredibly different way to think about code. A function is no longer a set of instructions in memory, it's a logical representation of functionality.
And yes, I know in C, you can set a variable to a function location, and then jump there, but it's painful to do and you have to do it explicitly, so it doesn't really create an abstraction.
I am fully convinced that if Java and .NET had a proper AOT toolchain from day 1, meaning beyond dynamic linking (NGEN) or commercial offerings from 3rd party JDKs, C's influence on FOSS world would have been much less than it achieved to be.
And we would already have achieved an UNIX like stack closer to what Inferno/Limbo was all about.
Would you mind naming a few such classes?
Why would arena allocation, or evrn good generational GC fail to deliver the performance when quick allocation / deallocation of (large) arrays is required?
Java just made a couple of wrong decisions regarding AOT and value types that are now taking years to correct course, while avoid breaking backwards compatibility.
If something like Modula-3 had been granted Java's success story, we wouldn't be talking about how GC languages don't have good support for value types.
Also I think C# structs do not have mutable fields, but I could be wrong.
Edit: it looks like C# structs are mutable, my mistake.
Maybe take some time to check the other ones?
As for value types in Common Lisp, even if one bit is lost for tagging, it doesn't make arrays, structs and primitive values, less of value types.
Unfortunately, Swift doesn't fix that AFAIK.
I’ve debugged too much java code where the programmers thought that ”thread-safe” meant ”no need to think about threading issues”.
The Obj-C community (or what's left of it) is trying to make a martyr of an error-prone, cumbersome programming language.
And unlike JNI they aren't protected by a VM wall.
I find that this assertion holds about as much water for Swift as it does for Rust, Swift is not even remotely close to C++'s in terms of complexity, and that's with building in mechanisms for performant memory safety, a concept which C++ literally just shits on to this day and for the foreseeable future.
But once you learn to use the more advanced features, your code just gets easier to write and maintain. I enjoy that I can pickup new language features in Swift one at a time, figuring out where each adds its best value, and occasionally refactoring to take advantage as part of my ongoing efforts to minimize code debt.
It’s not even close. Swift is (still) minimalist by comparison to C++.
Still not seeing the problem.
Pointers aren’t magic and aren’t hard.
Pointers, in practice, are hard. Even C-family compilers cannot safely reason about them in many (most) cases.
“As an embedded engineer I can’t agree that C “has problems” because it treats you like a big boy with your big boy pants on. :)”
Edit: Nah, that’s OK. Just downvote and scamper on. Make HN more like Reddit, that’s what this place needs!
C is really good at exploiting those, while at the same time giving programmers a feeling of power.
Isn't that why everyone loves python, solving a complex problem in a handful of easily readable lines of code?
Also... I’m a little concerned that your post has “we’re all equal” social justice vibe to it... which is silly. C is more powerful than because “safety features” aren’t there.... deplorable... LOL.
You try going a day without using something programmed in C.
No social justice vibe was meant. I was trying to say that we're all bad at dealing with the kind of errors which appear in a typical C or (perhaps to a lesser extent) C++ program.
I know that some people are able to do this more successfully than others because of skill, etc, but it's not just about certain individuals. As a whole, the C community has a really poor track record at security and safety and that has a lot to do with the language itself.
Thankfully there was already C++ for those of us that wouldn't move into such a limited language versus what something like Turbo Pascal 6.0 for MS-DOS was already capable of, feature wise.
Man... to listen to hackernews tell it... no one should use C!
I wonder how many comments describing how bad C is are from people on Linux machines?
The problem with C, versus other systems programming languages it that it its pointers, implicit conversions of array into pointers, integer operations, string and array bounds don't have any kind of validation.
On other systems languages disabling such validations is explicit.
C is like JavaScript in the browser, we have to put up with it because UNIX clones won the market of commodity OSes.
C on its own without UNIX, would have failed in the market.
On the desktop world it was already being replaced by C++, Smalltalk, VB, Delphi and 4GL before FOSS based on UNIX and C started to be widespread.
Unfortunately it is impossible to convince people on pure UNIX based OSes to use something else.
Fortunately, Apple, Microsoft, Google, Sony, Nintendo are able to set which programming languages one is allowed to use on their platforms and C is on the way out on their SDKs.
> The fundamental problem was Objective-C was built on top of C. C inherently has pointers. It has uninitialized variables. It has array overflows. It has all these problems that even if you have full control of your compiler and tool stack, you just can’t fix. To fix dangling pointers, you would have to fix lifetime issues, and C doesn’t have a framework to reason about that, and retrofitting that into a compatible way into the system just wouldn’t really work.
If you took away C from Objective-C, you couldn’t use C arrays on the stack, for example. And if you couldn’t do that, there’s entire classes of applications where the performance just wouldn’t be acceptable. We went around, around, around. We said the only way that this can make sense in terms of the cost of the disruption to the community is if we make it a safe programming language: not “safe” as in “you can have no bugs,” but “safe” in terms of memory safety while also providing high performance and moving the programming model forward.