C still wins by far when writing libraries that will be used by lots of other people. Doesn't matter what language they are using, they will be able to add in a library written in C very easily. However, C++ or Rust libraries, even with appropriate bindings for the target language, users of the library will need to bring in an entirely new compiler tool chain that may or may not exist on the target architecture. But the C tool chain will exist for that architecture and be robust.
For new side projects, pick what you want to use of course. But for existing codebases and projects that aspire to have maximum impact, I recommend fully considering tradeoffs instead of thinking in terms of "clear winners".
Which tooling? Just curious, asking entirely in good faith. My recollection is that the majority of tooling I was using with C++ worked with Rust - debuggers, profilers, and sanitizers being the main tools. Although I find that I use them much less frequently since I don't find debuggers as useful for the types of bugs I have these days, and sanitizers are only useful if you have unsafe, and profilers are cool but usually I just write benchmarks using a crate and then iterate from there.
All the major C compilers are also C++ compilers, and none are (yet) Rust compilers, so out of the gate, C++ has similar availability to C.
If you are speaking to missing a rust compiler built on gcc, that seems to be an ongoing project with some momentum.
Realistically the most widely used architectures are now supported by rustc through llvm... x86, arm, riscv, and even to some extent xtensa now.
Power, arc, mips, sparc, and some others aren't too far away if someone cared enough.
If Linux can support Rust, I'd think that's a good sign most project can use Rust.
The Linux kernel already does extensive bespoke tooling and it's low level enough to skip cargo and such. It's rare to see that approach in Rust projects in the wild.
https://overcast.fm/+LfVPHmBTo
Even if the tool chain exists, it must be adopted, unless you can rely on binaries being available for your end users, which will never be the case for a library which is just starting our. And adding another dependency to your build process, especially one as complex and with as many breaking version changes as C++, is a lot of work to take on.
Second, extern "C" exists.
Third, in what concerns clang and MSVC, the C library is actually implemented in C++ with extern "C".
Even if it's the "same" toolchain for compiling C++ as it is C, adding the complexity of an additional language to the build process, and the extra versioning headaches that C++ adds over C, is enough to kill library adoption.
As I said originally, providing bindings is not the challenge, it's all the other stuff.
https://thephd.dev/to-save-c-we-must-save-abi-fixing-c-funct...
[0] - The Annotated C++ Reference Manual
Two years ago, your argument would have implied that Rust would never be allowed into the Linux kernel, and yet here we are.
Except it's being used for serious development today
> going down the route of Java, i.e a corporate developed language with offshoots, which will end up with Rust being in the same crappy state.
So one of the most widely used applications programming languages in the world?
No, its being used for pet projects by people. Serious development = major companies using it in backends.
>So one of the most widely used applications programming languages in the world?
Because of CS programs, and legacy software written in java. Java has a community dedicated to pushing theoretical CS concepts into the language (much like Rust), while allowing things like a logging library to fetch code from anywhere on the internet and execute it, by default (which I would bet on would be the future of Rust given current trajectory)
You mean companies like Dropbox, Cloudflare, Amazon, Microsoft...? Are they too small to be relevant?
https://github.com/firecracker-microvm/firecracker/search?q=...
The fact that 'unsafe' even exists in Rust means it's no better than C with some macros.
Don't get me wrong, Rust has it's place, like all the other languages that came about for various reasons, but it's not going to gain wide adoption.
Future of programming consists of 2 languages - something like C that has a small instruction set for adopting to new hardware, and something that is very high level, higher than Python with LLM in the background. Everything in the middle is fodder.
Equating the existence of unsafe with C is laughable imho (it'd be barely comparable even if 100% of the rust code was in unsafe blocs, which never happens). Not even then it doesn't matter for the original point : rust is used in production for business critical functions, in large companies.
Parts of systems written in a language doesn't really mean anything for its adoption into mainstream. For example, Amazon uses Ruby heavily for a bunch of deployment stuff, but Ruby (sans Ruby on Rails that is in decline), is not really a mainstream language any more.
>Equating the existence of unsafe with C is laughable imho
Im not comparing it. The point is to demonstrate that unsafe exists for the sole reason of performance. In fast code you often want to directly access x[y] where x and y are variables, without having to run extra code around it. Its a well known computer science thing, as most of the code challenges given in interviews rely on this access pattern for optimal solutions.
And because of Rice theorem, a compiler cannot determine whether x[y] is always safe, as determining all the values y could take would involve running the program.
So as such, for all the advantages that Rust offers, you can have the same advantages with C with macros and LLVM extensions, albeit with less concise syntax.
https://www.microsoft.com/en-us/research/project/checked-c/
Similar arguments were used to justify Haskel about 6-7 years ago, and Haskel is pretty much dead in the water at this point.
The modern way to make a memory safe language is to focus on a high level language that doesn't require programmer to deal with memory directly, and then work on the compiler to make the resultant code optimal.
C++ keeps C's crap array type as its native array type. You need to reach into the C++ standard library to get this awkward library type, std::array<type,N> and then finally you get an array type that remembers how big it is and has some basic features like swap.
Microsoft security team is on the record that just because they are adopting Rust, they won't shy away from C++.
Example, Rust 1.0 had std::mem::uninitialized::<T>() which gives a T but it's obviously uninitialized. It's marked "unsafe" of course, but is that enough? Turns out they later realised that no, it's strictly never OK to do this, so the unsafe label was insufficiently cautious. Today std::mem::uninitialized is deprecated, Rust never removes stuff from the standard library, but you should not use this library call.
The type MaybeUninit<T> is the fix. Since MaybeUninit<T> might not be initialized, it's OK if it's not initialized, and since it might be T, it's OK for it to occupy the same amount of space as T. So, then we can initialize this memory, and tell the compiler it's initialized now, it's a T not a MaybeUninit<T>.
Can you guess how that works? It's pretty clever, and C++ could do almost the same trick, but it never has and my guess is it never will. If you don't know and are wondering, check that type definition carefully - MaybeUninit<T> is a union
For contrast, in his safety talk Bjarne Stroustrup just says as if it's obviously true, that it's safe to have uninitialized char arrays in C++. And his rationale sounds exactly like how std::mem::uninitialized happened - any possible value of a byte is a valid byte, so that's good enough, right? Nope, ask compiler engineers, there were plenty in the room when Bjarne said that, but he didn't ask them.
If we want to encourage Rust adoption, it is by having a middle path, not via Rust Advocacy Strike Force.
That only shuts the audience off, specially when Rust has a glass ceiling of depending on C++ infrastructure for its reference compilers.
And it's true that the rotten wood was better than nothing. Nobody is suggesting that NT or Linux should somehow have been developed in Rust in the 1990s. But likewise we shouldn't resist renewal in newer, better materials.
That applies to compiler internals too. Plenty of trouble down there for C++, it's just that C++ programmers can more often be sent away by assuring them that what they did was UB and so LLVM is entitled to miscompile it whereas the Rust people keep arriving with the receipts, in the form of LLVM IR that is lowered to machine code which makes no sense
Same applies to the runtimes of the languages I use at work, and GPGPU related tooling when not using shaders.
Maybe then do a Go/zig/D, focus on cranelift and fully bootstrap Rust, before trying to rewrite the world.
Unless you mean array of anything like in typeless dynamic languages I do not see anything awkward about STL arrays in C++.
And you might say, "Who cares? Even freestanding has the standard library". Nope, std::array wasn't added to freestanding. You can dig into the messy details for yourself if you want, but suffice to say your freestanding C++ doesn't have std::array
So the C++ language has "arrays" but they're garbage, and if you point out that the arrays are garbage you're told to use this library feature, which may not be available.
That doesn't make them garbage. That makes them annoying.
Which is fine if you write Windows desktop apps, but this is an array type, unlike a GUI widget, or an XML parser, it seems like I'd probably want an array type for this $1 per unit micro controller I'm writing firmware for. In Rust the nice array type works just fine, it's a proper first class type, it knows how big it is, mutable arrays coerce into a slice I can sort (only unstably, but hey, we're embedded firmware let's not get fancy), I can iterate over it properly... in C++ only the crappy C-style array is available unless I can butcher the std::array so that it works outside the hosted library. Ugh.
But I see that you bring Rust in here. If that's your cup of tea then use it. No need to spill venom. Personally if I am dealing with $1 micros I very much prefer C with some selected libs for embedded. Do not really have problems with it for such small tasks.
I have never perceived it as a problem. I do not think it really slows my programming. Personally I am the guy who would prefer function() vs fn() but without going into extremes of Java culture. Besides you can always alias it to whatever you want if your fingers are so sensitive.
Never been into this situation so from a practical standpoint it means zilch to me.
It makes writing (and hiring) a low-level project in C++ a much more complex task. It may have benefits, it may not. But C++ is so huge that it's difficult to judge whether it would offer an advantage.
And then there's the minefield of tooling in embedded development...
As a C++ developer, that sounds strange. Can you point me to some documentation about "dependent types"?
that being said, some do not want more macros either
Can be turned off on demand for relevant symbols.
> larger gap between source code and ISA
There's already a huge gap between C code and machine code (see: Undefined Behavior). C hasn't been a "portable assembler" for a very long time.
> impedance mismatch when working with C APIs
C++ has no problem working with C APIs.