In both those cases the K&R C model was very simple. You could decide you love how simple this model is, and when smarter compilers optimise it into a pretzel or other languages are faster that's OK. This code used to drive the serial port, now it does nothing, OK, don't use C to write such drivers. This code used to go real fast, now everybody else is faster, OK, don't use C if you need the best performance.
C89 and C99 choose different, making the language more complicated to keep addressing performance and compatibility. In C99 I can write the fast serial port driver, but it's significantly more complicated as a result. The beginner will definitely get it wrong and explaining why is pretty subtle.
Then C11 says actually you're not writing sequential programs, which was a crucial simplification in K&R C - the programs you can write do one thing at a time, in order, and then maybe stop. The memory model in C11 is needed because it says actually your programs might do more or different things at once.
Now, in reality by 2011 lots of people were writing C that's not actually sequential - after all SMP Linux long pre-dates C11. But those weren't legal C programs, they're GNU's dialect and so all bets are off. Nobody is claiming Linux is simple.
So C11 definitely isn't the simple language for a 1970s computer any more. C11 is a competitor with C++ or today Rust. And it doesn't fare so well by that comparison.
That code doesn't appear to be sequential from other threads is not the language's fault. It's just a fact of reality.
If you don't want to do SMP / lock-free programming, you don't have to pay for the complexity. You can still write "sequential programs" like it's K&R. Don't do multiple threads, and you don't have to care. You can also do multiple threads but use mutexes for synchronisation, everything will be fine.
Pretty much nobody uses restrict or volatile. There is some fringe stuff that is obsolete and maybe badly designed, but by and large you don't have to use it or interact with it. Compare this to other languages / ecosystems which have this amount of cruft times 100.
It's still this language where you can define a struct, then define a function that receives a pointer to the struct, and it does as you say, and you can actually read and understand the code a month later.
If you need to go fancy for a reason or another (most likely a bad reason), you can do that too, and of course you'll have to pay for it. But most likely, the complexity is not "cancerous" -- define a simple function interface with the most basic assumptions you require, and the complexity is pretty much isolated behind a simple pointer to an opaque structure.
> So C11 definitely isn't the simple language for a 1970s computer any more. C11 is a competitor with C++ or today Rust. And it doesn't fare so well by that comparison.
That's ridiculous and you know it.
"Faster but wrong" isn't really faster it's just wrong.
> That code doesn't appear to be sequential from other threads is not the language's fault. It's just a fact of reality.
What other threads? In a sequential programming language we certainly can't have "other threads".
> You can still write "sequential programs" like it's K&R.
"You can just not use the bits you don't like" is how we got C++ dialects that C++ proponents love to pretend don't exist. If the language is "simple" except for all the new bits that are complicated it's not simple.
C11 atomics would have been much better if they'd standardised existing practice instead of inventing something based around the application centric design C++ was inventing. It's nice that there's an acquire/release scheme one can reason with but a real shame that they conflated it with type annotations.
Next one is what, the C11 memory model? Doesn't take away any simplicity, just defines things better.