Indeed. I don't want to give the impression that C is just assembly. It gives all the advantages you name, and they are very important.
But I still say that C is a way of talking about same things you want to talk about in assembly, albeit while automating some tedious but important things like register allocation. You are still commanding the computer at a low level: still telling it which byte to put on which IO port or memory location.
Of course you can build higher level abstractions on this -- but only to a point. C compilers go wrong when they imagine a C program lives in such a higher level of abstraction -- whereas the other languages thrive on defining such abstract machines.
But you can't actually directly address I/O ports in C, and directly addressing memory (via pointer arithmetic which oversteps the bounds of an object, or which puns the type of an object) invokes undefined behavior. Both those things depend on details of the underlying architecture, ABI, and operating system, and are abstracted away in C.
But I still say that C is a way of talking about same things you want to talk about in assembly, albeit while automating some tedious but important things like register allocation. You are still commanding the computer at a low level: still telling it which byte to put on which IO port or memory location.
Of course you can build higher level abstractions on this -- but only to a point. C compilers go wrong when they imagine a C program lives in such a higher level of abstraction -- whereas the other languages thrive on defining such abstract machines.