This hack is a Rust compiler back-end. Backends get platform-specific instructions as an input, so non-trivial generated C code won't be portable. Users will need to either get pre-generated platform-specific source, or install the Rust compiler and this back-end to generate one themselves.
> When targeting the MSVC ABI, Rust additionally requires an installation of Visual Studio so rustc can use its linker and libraries.
> When targeting the GNU ABI, no additional software is strictly required for basic use. However, many library crates will not be able to compile until the full MSYS2 with MinGW has been installed.
...
> Since the MSVC ABI provides the best interoperation with other Windows software it is recommended for most purposes. The GNU toolchain is always available, even if you don’t use it by default.
In verification, C has piles of static analyzers, dynamic analyzers, test generators (eg KLEE), code generators (eg for parsing), a prover (Frama-C), and a certified compiler. If using a subset of these, C code can be made more secure than Rust code with more effort.
There's also many tools for debugging and maintenance made for C. I can also obfuscate by swapping out processor ISA's because C supports all of them. On the business end, they may be cheaper with lower watts.
I also have more skilled people I can hire or contract to do any of the above. One source estimated 7 million C/C++ developers worldwide. There's also a ton of books, online articles, and example code for anything we need. Rust is very strong in that last area for a new language but C/C++ will maintain an advantage, esp for low-level programming.
These are the reasons I'd use Rust if I wanted C or C++ for deployment. Likewise, I wish there was still a top-notch C++ to C compiler to get the same benefits I described with C's tooling.
And, if we discount the fact that "buying" a book is such a big hurdle, even more high quality academic text books and papers to boost; anything from embedded on the weirdest platforms, basic parsing, writing compilers, language design, high performance computing, teaching of algorithms, data structures, distributed systems, whatever!
edit: I even forgot to name operating system design plus game programming ; and of course accompanying libraries, compilers & build systems to cover all of those areas and use cases! edit2: networking, signal processing, automotive, learning about industry protocols and devices of any sort... if you explore computer science using C as your main language you are in the biggest candy store in the world with regards to what it is you want to learn about or do or implement...
All that is language-agnostic and doesn’t necessarily have anything to do with C.
And C maps so directly to so many concepts; it's easy to pick up any of those topics with C; and it being so loose makes it even perfect to explore many of those areas to begin with, since very quickly you're not fighting the language to let you do things.
why is my executable 20 mb, not as performant as a 50 kb C file & doesn't build a year later if I try to build with 89 new versions of those packages
obligatory xkcd reference: https://imgs.xkcd.com/comics/dependency_2x.png this is what package managers lead to
(and yes, numbers were exaggerated; I picked something trivial like a csv parser pulling in 89 packages for effect; the underlying principle sadly holds true)
In C this was actually a less problem since you had to copy-paste the shared code into your program and at some level you were manually reviewing it all the time.
Also in Rust people tend to write very small libraries and that increases the number of dependencies. However, many still not follow SemVer et. al and packages tend to be unstable too. On top of additional security issues. They maybe be useful for a short time but in many cases you might need to think the lifetime of your application up to 10 years.
It's not a problem with Rust specifically though. It's not unique to Rust.
> Also in Rust people tend to write very small libraries and that increases the number of dependencies. However, many still not follow SemVer et. al and packages tend to be unstable too.
Don't use random unpopular crates maintained by unknown people without reviewing the code.
You kind of have a point behind dependency hell, but the flip side is that one needn't become an expert on universal CSV parsing just to have a prayer of opening them successfully.
Which means all that high quality teaching material is DECADES old. Rust development is centralised and therefore the docs are always up-to-date, unlike C/C++ which is a big big mess.
I could spurr into an essay of what kind of lack of understanding you just portrayed about the world, but I won't.... I won't...
Exactly. For context see my original comment above about C/C++ books being paid.
There are so many free learning resources for these languages that it is ridiculous to say that you need books to learn them. The books are great, but non-essential. If you insist on reading books, there is an ancient invention called a library that you can use for free.
The main exceptions that you actually would want to use would be the ability to declare variables anywhere in a block and use single line // comments from C++ in C99. Most C programmers do not even know about most of the things added in newer C standards beyond those and perhaps a handful of others.
As for C++, there is nothing at that link that says you need a textbook to learn C++ (and the idea that you need one is ludicrous). The textbooks are suggested resources. There are plenty of free resources available online that are just as good for learning C++.
You would be better off learning C before learning C++. C++ is a huge language and its common history with C means that if you do not understand C, you are likely going to be lost with C++. If you insist on learning C++ first, here is the first search result from DuckDuckGo when I search for "learn C++":
You will likely find many more.
For what it is worth, when I was young and wanted to learn C++, I had someone else tell me to learn C first. I had not intended to follow his advice, but I decided to learn C++ by taking a university class on the subject and the CS department had wisely made learning C a prerequisite for learning C++. I later learned that they had been right to do that.
After learning C++, I went through a phase where I thought C++ was the best thing ever (much like how you treat Rust). I have since changed my mind. C is far better than C++ (less is more). I am immensely proud of the C code that I have written during my life while I profoundly regret most of the C++ code that I have written. A particular startup company that I helped get off the ground after college runs their infrastructure on top of a daemon that I wrote in C++. Development of that daemon had been a disaster, with C++ features making it much harder to develop than it actually needed to be. This had been compounded by my "use all of the features" mentality, when in reality, what the software needed was a subset of features and using more language features just because I could was a mistake.
I had only been with the startup for a short time, but rejoined them as a consultant a few years ago. When I did, I saw that some fairly fundamental bugs in how operating system features were used from early development had gone unresolved for years. So much of development had been spent fighting the compiler to use various exotic language features correctly that actual bugs that were not the language's fault had gone unnoticed.
My successor had noticed that there were bugs when things had gone wrong, but put band-aids in place instead of properly fixing the bugs. For example, he used a cron job to restart the daemon at midnight instead of adding a missing `freeaddrinfo()` call and calling `accept()` until EAGAIN is received before blocking in `sigwaitinfo()`. Apparently, ~3000 lines of C++ code, using nearly every feature my younger self had known C++ to have, were too complicated for others to debug.
One of the first things I did when I returned was write a few dozen patches fixing the issues (both real ones and cosmetic ones like compiler warnings). As far as we know, the daemon is now bug free. However, I deeply regret not writing it in C in the first place. Had I written it in C, I would have spent less time fighting with the language and more time identifying mistakes I made in how to do UNIX programming. Others would have been been more likely to understand it in order to do proper fixes for bugs that my younger self had missed too.
Sorry, it says that in their FAQ[0]. It also says "Should I learn C before I learn C++?" "Don’t bother." and proceeds to advertise a Stroustrup book[1].
[0]: https://isocpp.org/wiki/faq/how-to-learn-cpp#start-learning
[1]: https://isocpp.org/wiki/faq/how-to-learn-cpp#learning-c-not-...
> If you insist on learning C++ first, here is the first search result from DuckDuckGo when I search for "learn C++":
I don't insist on learning C++ and I even agree with you that C is better. But I have a problem with learning from non-authoritative sources, especially random websites and YouTube tutorials. I like to learn from official documentation. For C there appears to be no official documentation, and my intution tells me that, as nickpsecurity mentioned, the best way is to read the K&R book. But that brings us back to my original point that you have to buy a book.
> was the one true way (like you seem to have been with Rust)
I don't think there exists any one true way. It depends on what you do. For example I like Rust but I never really use it. I pretty much only use TypeScript.
> was the best thing ever (much like how you treat Rust)
I would actually prefer Zig over Rust but the former lacks a mature ecosystem.
> For example, they used a cron job to restart the daemon at midnight instead of adding a missing `freeaddrinfo()` call and calling `accept()` until EAGAIN is received before blocking in `sigwaitinfo()`.
This sounds like a kind of bug that would never happen in Rust because a library would handle that for you. You should be able to just use a networking library in C as well but for some reason C/C++ developers like to go as far as even implementing HTTP themselves.
> After learning C++...
Thanks for sharing your story. It's wholesome and I enjoyed reading.
They also would say "Don't bother" about using any other language. If you listen to them, you would never touch Rust or anything else.
> But I have a problem with learning from non-authoritative sources, especially random websites and YouTube tutorials. I like to learn from official documentation. For C there appears to be no official documentation, and my intution tells me that, as nickpsecurity mentioned, the best way is to read the K&R book. But that brings us back to my original point that you have to buy a book.
The K&R book is a great resource, although I learned C by taking a class where the textbook was "A Book On C". I later read the K&R book, although I found "A Book on C" to be quite good. My vague recollection (without pulling out my copies to review them) is that A Book On C was more instructional while the K&R book was more of a technical reference. If you do a search for "The C programming language", you might find a PDF of it on a famous archival website. Note that the K&R book refers to "The C programming language" by Kerninghan and Ritchie.
Relying on "authoritative" sources by only learning from the language authors is limiting, since they are not going to tell you the problems that the language has that everyone else who has used the language has encountered. It is better to learn programming languages from the community, who will give you a range of opinions and avoid presenting a distorted view of things.
There are different kinds of authoritative sources. The language authors are one, compiler authors are another (although this group does not teach), engineers who actually have used the language to develop production software (such as myself) would be a third and educational institutions would be a fourth. If you are curious about my background, I am ths ryao listed here:
https://github.com/openzfs/zfs/graphs/contributors
You could go to edx.org and audit courses from world renowned institutions for free. I will do you a favor by looking through what they have and making some recommendations. For C, there really is only 1 option on edX, which is from Dartmouth. Dartmouth is a world renowned university, so it should be an excellent teacher as far as learning C is concerned. They appear to have broken a two semester sequence into 7 online courses (lucky you, I only got 1 semester at my university; there was another class on advanced UNIX programming in C, but they did not offer it the entire time I was in college). Here is what you want to take to learn C:
https://www.edx.org/learn/c-programming/dartmouth-college-c-...
https://www.edx.org/learn/c-programming/dartmouth-college-c-...
https://www.edx.org/learn/c-programming/dartmouth-college-c-...
https://www.edx.org/learn/c-programming/dartmouth-college-c-...
https://www.edx.org/learn/c-programming/dartmouth-college-c-...
https://www.edx.org/learn/linux/dartmouth-college-linux-basi...
https://www.edx.org/learn/c-programming/dartmouth-college-c-...
There is technically a certificate you can get for completing all of this if you pay, but if you just want to learn without getting anything to show for it, you can audit the courses for free.
As for C++, there are two main options on edX. One is IBM and the other is Codio. IBM is a well known titan of industry, although I had no idea that they had an education arm. On the other hand, I have never heard of Codio. Here is the IBM sequence (note that the ++ part of C++ is omitted from the URLs):
https://www.edx.org/learn/c-programming/ibm-fundamentals-of-...
https://www.edx.org/learn/object-oriented-programming/ibm-ob...
https://www.edx.org/learn/data-structures/ibm-data-structure...
There actually are two more options on edX for C++, which are courses by Peking University and ProjectUniversity. Peking University is a world class university in China, but they only offer 1 course on edx that is 4 weeks long, so I doubt you would learn very much from it. On the other hand, I have never heard of ProjectUniversity, and their sole course on C++ is only 8 weeks long, which is not very long either. The 3 IBM courses together are 5 months long, which is what you really want.
> I pretty much only use TypeScript.
Learn C, POSIX shell scripting (or bash) and 1 functional programming language (Haskell is a popular choice). You will probably never use the functional programming language, but knowing about functional programming concepts will make you a better programmer.
> This sounds like a kind of bug that would never happen in Rust because a library would handle that for you. You should be able to just use a networking library in C as well but for some reason C/C++ developers like to go as far as even implementing HTTP themselves.
First, I was using a networking library. The C standard library on POSIX platforms is a networking library thanks to its inclusion of the Berkeley sockets API. Second, mistakes are easy to criticize in hindsight with "just use a library", but in reality, even if you use a library, you could still make a mistake, just as I did here. This code also did much more than what my description of the bug suggested. The reason for using asynchronous I/O is to be able to respond to events other than just network I/O, such as SIGUSR1. Had I not been doing that, it would not have had that bug, but it needed to respond to other things than just I/O on a socket.
I described the general idea to Grok and it produced a beautiful implementation of this in Rust using the tokio "crate". The result had the same bug that the C++ code had, because it made the understandable assumption my younger self made that 1 SIGIO = 1 connection, but that is wrong. If two connection attempts are made simultaneously from the perspective of the software, you only get 1 SIGIO. Thus, you need to call accept() repeatedly to drain the backlog before returning to listening for signals.
This logical error is not something even a wrapper library would prevent, although a wrapper library might have prevented the memory leak, but what library would I have used? Any library that wraps this would be a very thin wrapper and the use of an additional dependency that might not be usable on then future systems is a problem in itself. Qt has had two major version changes since I wrote this code. If I had used Qt 4's network library, this could have had to be rewritten twice in order to continue running on future systems. This code has been deployed on multiple systems since 2011 and it has never once needed a rewrite to work on a new system.
Finally, it is far more natural for C developers and C++ developers to use a binary format over network sockets (like I did) than HTTP. Libcurl is available when people need to use HTTP (and a wide variety of other protocols). Interestingly, an early version of my code had used libcurl for sending emails, but it was removed by my successor in favor of telling a PHP script to send the emails over a network socket (using a binary format).
It's not just accept. If your socket is non-blocking the same applies to read, write, and everything else. You keep syscalling until it returns EAGAIN.
> I described the general idea to Grok and it produced a beautiful implementation of this in Rust using the tokio "crate". The result had the same bug that the C++ code had, because it made the understandable assumption my younger self made that 1 SIGIO = 1 connection, but that is wrong.
I don't know what your general idea was but tokio uses epoll under the hood (correctly), so what you are describing could only have happened if you specifically instructed grok to use SIGIO.
> Finally, it is far more natural for C developers and C++ developers to use a binary format over network sockets (like I did) than HTTP.
Designing a custom protocol is way more work than just using HTTP. <insert reasons why http + json is so popular (everyone is familiar with it blah blah blah)>.
You do not call read/write on a socket that is listening for connections.
> I don't know what your general idea was but tokio uses epoll under the hood (correctly), so what you are describing could only have happened if you specifically instructed grok to use SIGIO.
That is correct. There is no other way to handle SIGUSR1 in a sane way if you are not using SIGIO. At least, there was no other way until signalfd was invented, but that is not cross platform. epoll isn't either.
> Designing a custom protocol is way more work than just using HTTP. <insert reasons why http + json is so popular (everyone is familiar with it blah blah blah)>.
You are wrong about that. The code is just sending packed structures back and forth. HTTP would overcomplicate this, since you would need to implement code to go from binary to ASCII and ASCII to binary on both ends, while just sending the packed structures avoids that entirely. The only special handling this needs is to have functions that translate the structures from host byte order into network byte order and back, to ensure that endianness is not an issue should there ever be an opposite endian machine at one end of the connection, but those were trivial to write.
Do yourself a favor and stop responding. You have no idea what you are saying and it is immensely evident to anyone who has a clue about software engineering.
Among other things, this would only work if your client is written in a language that supports C structures.
> Do yourself a favor and stop responding. You have no idea what you are saying and it is immensely evident to anyone who has a clue about software engineering.
Says the one who didn't know how to use non-blocking sockets.
> That is correct. There is no other way to handle SIGUSR1 in a sane way if you are not using SIGIO. At least, there was no other way until signalfd was invented, but that is not cross platform. epoll isn't either.
```
use std::io;
use tokio::{
net::UnixListener,
select,
signal::unix::{SignalKind, signal},
};#[tokio::main(flavor = "current_thread")]
async fn main() -> io::Result<()> {
let mut signal = signal(SignalKind::user_defined1())?;
let listener = UnixListener::bind("./hi")?;
loop {
select! {
_ = signal.recv() => {
todo!();
}
_ = listener.accept() => {
todo!();
}
}
}
}```
Such languages are used at both ends. Otherwise, this would not have been working in production for ~13 years.
> Says the one who didn't know how to use non-blocking sockets.
Neither did you until you learned it. If you successfully begin a career in software engineering and years later, have the humility to admit the mistakes you made when starting out for the benefit of others, you will deserve to have an incompetent know it all deride you for having been so kind to admit them, just like you are doing to me here.
Anyone with a modicum of programming knowledge can write code snippets free from mistakes immediately after being told about the mistakes that would be made when given a simplified explanation of one thing that is done in production software. The problem with software engineering is that nobody tells you everything you can do wrong before you do it, and you are not writing code snippets, but production software.
I wouldn't "deride" you if you weren't acting arrogant and calling me incompetent or whatever.
> The problem with software engineering is that nobody tells you everything you can do wrong before you do it
Maybe, but the docs definitely tell you about EAGAIN and freeing memory after you're done using it. In Rust many kinds of logical errors you could potentially have made are eliminated by the type system though. For example I wrote a news scraper in Rust and ran it locally a couple times to see that it works, and it's been running for half a year now on a VPS and I never had to touch it or restart anything.
This is great advice, thanks!
This is very different than Rust where every new version is abandonware after 6 weeks and the compiler does not let you specify that your code is from a specific version.
Right, the docs never get out of date if the thing they document never changes. Can you say the same about C++ though? I’ve heard they release new versions every now and then. My robotics teacher didn’t know ‘auto’ is a thing for example.
If your argument was C then sure thats a C23 feature (well the type inference type of auto ) and is reasonably new.
This is much more a reflection on youe professor than the language. C++11 was a fundamental change to the language, anyone teaching or using C++ in 2025 should have an understanding of how to to program well in a 14 year old version of said language...
> anyone teaching or using C++ in 2025 should have an understanding of how to to program well in a 14 year old version of said language...
If the current year is 2025 then 14 years ago is 2011 which is not that long ago.
> If your argument was C then sure thats a C23 feature (well the type inference type of auto ) and is reasonably new.
Grandparent comment is arguing that Linux was written in C89 until a few days ago so decades old books on C aren't actually outdated.
When a lot of modern CS concepts wwre first discovered and studied in the 70s, there's no point arguing that old books are useless. Honestly there may be sections of old books that are useless but in the whole they are still useful.
Then what’s the point of adding any new features?
That said, when you learn a foreign language, you do not learn every word in the dictionary and every grammatical structure. The same is true for programming. You just don't need to have a more up to date book than one on C89 to begin learning C.
There is no `-std=1.85` in rust 1.86. You do get `-std=c++98` in both g++ and clang++. A book on C or C++ is still useful even decades later since the version of C or C++ described does not become abandonware at some well defined point after release, unlike Rust releases.
Given a version number MAJOR.MINOR.PATCH, increment the:
MAJOR version when you make incompatible API changes
MINOR version when you add functionality in a backward compatible manner
PATCH version when you make backward compatible bug fixes
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.What kind of versioning scheme does C/C++ use?
That sounds like Rust editions.
The only reason you see people grouping the two languages together is due to history. They are both derivatives of an ancient prestandard form of C called K&R C. They both have different standards committees who had different ideas about how to move forward from K&R C. The result is that C compilers were extended to support both, and that extension continues to this day despite the divergence between the two languages. The C standards committee accepted some of the changes the C++ committee made to K&R C, although the C++ standards committee does not reciprocate by accepting changes made by the C standards committee. This is making them increasingly different languages.
Try to spend time learning how other things work instead of posting replies that attempt to reinterpret everything people tell you through a Rust lens whenever someone is kind enough to answer your questions like you are doing here. It is like asking people how Chinese works and then telling them “English does it this way”. The “nothing matters but <insert language here>” mentality that causes that is going to annoy a large number of people from whom you would otherwise be able to learn.
Do you have any specific evidence? Rust ecosystem is known for libraries that sit on crates.io for years with no updates but they are still perfectly usable (backward-compatible) and popular. Projects usually specify their MSRV (minimum supported Rust version) in the README.
I ended up switching to Python for job requirements after getting through half the book. If I re-learn C, I'll go back to it. If it were C++, that would be a totally, different story since they kept piling features on over time.
I admit there is many great products that are written in C that aren’t going anywhere any time soon, notably SQLite, but there is no reason to write new software in C or C++.
Personally, I'd use both Rust and C with equivalent code. The Rust types and borrow checker give some extra assurance that C might not have. The C tooling gives extra assurance Rust doesn't have. Win, win. If I want, I can also do a certified compile or cross-compile of the Rust-equivalent, C code.
```rust
#[kani::proof]
fn main() {
let mut array: [i32; 10] = kani::any();
array.sort_unstable();
let index: usize = kani::any_where(|i| *i > 0 && *i < array.len());
assert!(array[index] >= array[index - 1]);
}
```https://www.absint.com/astree/index.htm
By the way, C has a formally verified C compiler:
On Astree, I couldn't believe it supported all language constructs. I found this on your link:
"and is subject to the same restrictions as Astrée for C.
The high-level abstraction features and template library of C++ facilitate the design of very complex and dynamic software. Extensive use of these features may violate the established principles of safety-critical embedded software development and lead to unsatisfactory analysis times and results. The Astrée manual gives recommendations on the use of C++ features to ensure that the code can be well analyzed. For less constrained (less critical) C++ code, we recommend using the standalone RuleChecker."
So, it still does require a language subset that reduces complexity to benefit from the full analysis. They have greatly expanded what errors they catch since I first read about them. So, thanks for the link.
1. C/C++ developers who are used to C/C++ and don’t want to learn Rust.
2. Go developers who claim Rust is too difficult and unreadable.
Which one is you?
I've been working with C for over 30 years, both professionally and a hobbyist. I have experimented with Rust but not done anything professionally with it. My gut feel is Rust is too syntactically and conceptually complex to be a practical C replacement. C++ is also has language complexity issues, however it can be adopted piecemeal and applied to most existing C code.
It’s not just a couple. We’ve seen virtually all JS tooling migrate to Rust, and there is many more things but I can’t remember by name.
That would depend on what you use C for. But I sure can imagine people complain that Rust gets in the way of their prototyping while their C code is filled with UB and friends.
Monomorphization is what causes long build times, but it brings better performance than dynamic dispatch.
> lack of stability
There was another comment which also never elaborated on how Rust is not stable.
> supply chain issues
Not a language issue, you choose your dependencies.
> no proper standard, not enough different implementations
Is that a practical problem?
> no dynamic linking
There is.
> There is.
Eh, I'm a Rust fan, and I hate the dynamic linking situation too.
I genuinely cannot see how Rust would be able to scale to something usable for all system applications the way it is now. Is every graphical application supposed to duplicate and statically link the entire set of GNOME/GTK or KDE/Qt libraries it needs? The system would become ginormous.
The only shared library support we have now is either using the C ABI, which would make for a horrible way to use Rust dependencies, or by pinning an exact version of the Rust compiler, which makes developing for the system almost impossible.
Hopefully we'll get something with #[export] [1] and extern "crabi" [2], but until then Rust won't be able to replace many things C and C++ are used for.
You don't have to statically link C libraries.
As in, if there will ever be a Rust equivalent of KDE/GNOME (e.g. maybe COSMIC), it will have similar libraries. They will have to be in Rust, and will have to be statically linked. And they will eventually grow up to be the size of KDE/GNOME (as opposed to the tiny thing COSMIC is now).
Of course you shouldn't do that, but it's a problem rust-to-c conversion would solve.
Another reason I could think of is the desire to take something licensed in a way you don't like, written in Rust, for which you'd like to call into the private API in your production code, but don't want the legal obligations that come with modifying the source code to expose the methods the normal way.
I don't think either use case is worth the trouble, but there are theoretically some use cases where this makes sense.
It's also something I might expect someone who doesn't know much about Rust or FFIs outside of their own language might do. Not every language supports exporting methods to the C FFI, and if you're coming from one of those and looking to integrate Rust into your C you might think that translation is the only way to do it.
Most likely, it's a way rust haters can use rust code without feeling like the "other side" has won.