Most things are harder to understand if you're not grounded in the knowledge that's "underneath". When I taught CS it got a lot easier when I started my students on programming a very simple "machine", a simulated decimal computer with decimal opcodes whose memory consisted of decimal registers and decimal addresses. They would put in very short programs to, for example, add a series of numbers to get a total. Then they would single step it to watch what was happening. They could hold down the "enter" key and watch it run "fast".
I'm sure almost everyone on SO wonders why it is useful to get so basic. We forget what it was like not knowing how to program. Playing with such a toy computer puts in place concepts without which you can't program, such as the ideas that computation is a step-by-step process, using a small number of basic primitives to build up programs, and the concept of memory variables as places where numbers are stored, in which the address or name of the variable is distinct from the number it contains. There is a distinction between the time at which you enter the program, and the time at which it "runs". I liken learning to program as crossing a series of "speed bumps", such as very simple programs, then loops and subroutines, then arrays, then sequential I/O, then pointers and data structure. All of these are much easier to learn by reference to what a computer is really doing underneath.
Finally, when getting to C, pointers are confusing though K&R did a very good job of explaining them. The way I learned them in C was to know how to read them - right to left. Like when I see int *p in my head I say "p points to an int". C was invented as one step up from assembly language and that's what I like about it - it is close to that "ground". Pointers, like anything else, are harder to understand if you don't have that grounding.