But often you just need to get the job done, and have limited options available.
Perhaps in 50-100 years, people looking back at software from this era won't be able to understand how we managed to make it work at all.
I haven't met or know anyone mastering C/C++ (especially C++), and doubt I'll ever hear about one.
I’d say I had a working knowledge of C++ after about a year ramping up on a codebase based on a mature C++ framework.
That was after years of writing reliable, performant C code. My C++ is now significantly better than the C I can produce, on both fronts, and at the same time.
I’m also much more productive as a side effect of that.
C can definitively be mastered. C at it's core is pragmatic minimalism. The basic ideas are very simple. If you want to be a language lawyer and know the standard completely (including all historical accidents), it can get complex, but still manageable. But anyways, you shouldn't be a language lawyer. That's not C. Make maintainable programs instead, stay in the middle of the road.
C gets out of the programmer's way. It's not about mastering C, but about mastering programming. And while I agree there's much bad C software out there: I haven't seen one maintainable non-bloated Java project. Here is one master of C that I'm sure you know: Linus Torvalds. Of course there are many, many more. Just remember it's not about C, but programming machines in general.
I also haven't seen one large-scale network-facing C project written using reasonable development practices (i.e. not absurdly expensive formal verification) that hasn't had some sort of terrible remote code execution vulnerability. By contrast, Java programs tend to be far less vulnerable to this kind of problem. (The closest thing is probably bugs with attacker controlled java.io.Serializable, which while severe are much less frequent than RCE in C programs.)
> Here is one master of C that I'm sure you know: Linus Torvalds.
I agree that Linus is a master of C. Linux is also an excellent example of the above problems with C.
This has gotten a lot better with static code analysis (clang-analyzer, Coverity, ...) and whitebox-fuzzing (libfuzzer, afl, ...). Both simply point you to the bugs and don't require a formal spec.
Together with Valgrind, these tools have revolutionized C programming for me.
Use your tools wisely. Architect programs for clear data flow. Validate inputs as soon as possible. Don't do (de)serialization by hand.
By all means use a managed "memory safe" language if you have many data accesses that are not behind a validation gateway. But for large amounts of data or complex software, that's still not an option. C is still the only language in which I can write software of advanced complexity - because it does not get in my way.
Mesa/Cedar at Xerox PARC, Topaz at DEC/Olivetti, Oberon at ETHZ, JavaOS at Sun, Singularity/Midori at Microsoft Research
> Game Engines
Unity is slowly rewriting parts of their C++ pipeline with C#, after their IL2CPP compiler got mature.
Then there are game engines like Xenko being done.
Also being with one foot into games since the 80's, I remember the transitions "Pascal/C are too slow, we stick Assembly", "C++ is too slow, we stick with C", now we are in "JavaScript/C#/Java are too slow, we stick with C++" phase.
If that's true, how come there are almost no widely used network facing C programs that didn't have plenty of security vulnerabilities?
(Anything written by Daniel J. Bernstein doesn't count, because there's no way he's a mere mortal. :))
Postfix is also much more widely used than qmail.
Goto, you just can't do without it.
Also not saying that in some cases even C is too much abstraction. But in general, its memory abstractions and its function call abstraction have proved to be very effective helping humans develop in a modular fashion.
Strange, the last time I used it I was still doing Basic in the early 90's, or when I do some Assembly programming.
So yeah, we can do without it, as long as the languages are powerful enough.
Not saying there's no use for backward gotos, just don't remember ever needing them. Maybe they could be useful for some C code generation cases or perhaps for retrying some operation?
What really annoys me are C++ exceptions used for flow control. Surprise gotos. I loved exceptions long ago at first, but over time the feeling has shifted more and more towards hate. Exceptions make code bases so much harder to understand. Especially when combined with inheritance.
There are indeed C compilers that don't support recursion (or function re-entrancy). What does the standard say about stacks?
Recursive function calls shall be permitted, both directly and indirectly through any chain of other functions.
Stacks, I don't know. I only care about the concept (and semantics) of function calls. The call stack is an implementation detail. I wouldn't be surprised if the concept of a call stack was not part of the standard.[1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
> For such an object that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way. (Entering an enclosed block or calling a function suspends, but does not end, execution of the current block.) If the block is entered recursively, a new instance of the object is created each time. The initial value of the object is indeterminate.
Pragmatic minimalism as it was for the hardware at the beginning of the 1970s, to be exact.
The C machine model says nothing about vector instructions, instruction re-ordering, NUMA, GPGPU, IO ports, Harvard architecture, multi-core.
Modern compilers are still rather bad at vectorization. What's worse, those optimizations are often unstable. A small change might make code several times slower. Performance regression tests and when that fails, vector intrinsics are a must.
template<template<class>, template<class, template<uint>>, class>
before breakfast.There are equally important reasons why C's usage has been in steady decline from the '90s to today.
More important was it was the only language that really worked on DOS, which ruled the computer biz for 10 years. I would guess 80% of programming was done for DOS, and C was a very good fit for the 640K systems.
C and C++ had no special place on the spectrum of programming languages usage, unless we were porting code between MS-DOS and UNIX.
Until it was time to move into Windows, and anyone not using C or C++ started to be left behind, manually writing FFI wrappers (e.g. Turbo Pascal/Delphi) and we eventually migrated to one of them.
We've been hearing "C isn't the problem, bad programmers are the problem" for 40 years. This has continued to perpetuate the problems with the language.
I mean, I certainly agree that there are no alternatives to C now for certain domains, but there are real problems with it that aren't solved by just "treating it with proper respect".