The C89/99 standard is rather small, it is relatively easy (certainly compared to C++) to know it almost fully. But the devil is in the details, it is very important to fully understand how C treats pointers, and how close to the hardware the language is, this is where the caveats are.
C doesn’t do anything particularly strange with pointers. Most of the weirdness comes from arrays not actually being arrays and sizeof being a primitive with a surprising behaviour in my experience. Apart from that you have to understand the difference between the stack and the heap and how your system treats malloc (well understanding that it can fail goes a long way) but that’s pretty much it.
There are probably some sharp corners I’m not thinking of around type conversions but that’s the kind of thing you expect from a strongly typed language.
Most of the caveats are in how compilers treat C rather than how close it is to the hardware to be honest.
Indeed C doesn't do much with pointers, it is very close to a cpu register containing a memory address. If you are used to higher level languages, it is odd. You can simply cast a pointer to one type to a pointer to another type. This is very often used to introduce OO like behaviour, but you need to understand how it works under the hood. Pointer arithmetic is sensitive to types though, so C is a bit smart in that way.