The worst thing with C pointers was for me that the asterisk is inexplicably used both to declare a pointer and a COMPLETELY different operation of dereferencing a pointer.
I still don't understand this decision. I think it should've been like int^ p = &i; ... or ... int i = *p;
Everything clicked ironically when I went even deeper and studied assembly language. Then following pointers to data vs just reading pointers becomes very clear and explicit.