You only need that abstraction if you're doing low level bit/byte bashing and I/O, or there's some chance you may run out of memory and need to handle that manually.
That applies to a tiny slice of all possible applications.
There are far more useful modern abstractions that don't need to make those assumptions.
But someone's got to write drivers and someone's got to write the thing that connects the higher levels to the metal.
That PDP-11 from the seventies had ADC/SBC (addition/subtraction with carry) in its instruction set, the result of MUL was twice the size of the inputs (i.e., multiplying two ints produced a long), and DIV produced both the quoitient and the remainder. None of that is visible from C and yet people keep clamoring that "C is close to the metal". Bah, humbug: while " * p++" and " * --p" idioms translate directly into an addressing mode particular for PDP-11 — most other architectures don't have autoincrement/decrements — there is no specific support for " * ++p " or " * p--" in the machine itself.
No amount of abstraction under any language will isolate you from such memory model.
I may be being pedantic or outright wrong (since it's been a while since I used C), but I don't think C can address memory by individual bit.
You have to read one or more bytes from memory, twiddle the bits in them, using C's bitwise operators (like !, &, | and tilde), and then write the changed bytes back to memory at the same addresses you read them from. At least for the earlier C versions I used, this was the case, IIRC.
And to read and write those bytes, you do it via scalar variables like ints or longs, or via structs or arrays, or via pointers. Or using library functions like memset().
It's true that almost nothing works the way it's presented: the computer doesn't necessarily actually do the instructions you specify, it does its machine commands that are compiled. It also doesn't necessarily even do them in the order they are specified. The memory isn't actually a big continuous space, it's mapped as virtual memory. The actual memory isn't used in that way either, there's a hierarchy of NUMAed caches between the CPUs and the actual memory.
But it's a useful abstraction. Partly because a lot of the above things are built so that the abstraction works. But also because we want it to look that way, and it's kinda natural to let programmers imagine a virtual machine that works that way.