For example, C has pointer provenance, so pointers arent just addresses. Thats why type punning is such a mess. If a lang claims to be super close to the hardware this seems like a very weird thing.
What makes C feel free for programming is that instead of prescribing an implementation paradigm, it instead exposes a computing model and then lets the programmer write whatever is possible with that (and also what is not -- UB). And a lot of higher level abstractions are quickly implemented in C, e.g. inheritance and polymorphism, but then they still allow to be used in ways you like, so you can not just do pure class inheritance, but get creative with a vtable, or just use another vtable with the same object. These are things you can't do when the classes are a language construct.
My gripe is only with people acting like the C abstract machine doesn't exist and C is just syntax sugar for a bit of assembly. It's a bit more involved than that.
Most people have no understanding of an abstract machine though the very idea of a high-level programming language is based on it.
The C Language Standard itself specifies "Program Execution" only on a "Abstract Machine". Mapping that abstract machine to an ISA/Memory on real hardware is the task of the C compiler. It can do this in any manner as long as the observable behaviour of the program is "as-if" it ran on the abstract machine.
Relevant quote:
A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible executions of the corresponding instance of the abstract machine with the same program and the same input.
Further Resources;
Wikipedia Abstract machine - https://en.wikipedia.org/wiki/Abstract_machine
Abstract machines for programming language implementation (pdf) - https://www.rw.cdl.uni-saarland.de/people/diehl/private/pubs...
The Abstract Machine: A Pattern for Designing Abstract Machines (pdf) - https://www.plopcon.org/pastplops/plop99/proceedings/garcia/...