Earlier quoted context omitted.
In practice C let's you control memory layout just fine. You might need to use __attribute__((packed)), which is technically non standard. I've written hardware device drivers in pure C where you need need to peek and poke at specific bits on the memory bus. I defined a struct that matched the exact memory layout that the hardware specifies. Then cast an integer to a pointer to that struct type. At which point I coul…
Now split the struct across registers in C. You are aware that some of those casting tricks are UB, right?
If you want to control register layout, then C is not going to help you, but that is not typically what is meant by "memory layout".
And if you want to control cache usage ... Some architectures do expose some black magic which you would need to go to assembly to access. But for the most part controlling cache involves understanding how the cache works, then controlling the memory layout and accesses to work well with the cache.