I'll add an idea for a simple place where pointers could help: Try making an image buffer struct with several functions to create, destroy, and access specific pixels. (Think a function like uint8_t* image_get_pixel(image img, x, y) that returns a pointer to a specific place in your array corresponding to that pixel, which can be indexed like so: image_get_pixel(img, 3, 4)[2] and suddenly you have pixel 4, 5's blue channel. Maybe that isn't too readable so maybe you could do image_get_blue(img, 3, 4)? I don't really know. Programming is hard.) Try to make it use only one malloc() call when creating/freeing the image data pointer. Also try making it with a split header / file combination so you can use it more like a library.
Fucking around with multidimensional data like images will make you become really comfortable with pointer arithmetic very quickly.