If you understand the syntax, then the only way to become "fluent" in a language is to use it.
Using C is a good way to keep things simple and get close to the "metal", but it isn't the same as C++, so ultimately I would advise using C++ if you wish tolearn C++. (i.e Don't learn Latin if you want to be fluent in Italian, even though Latin will give you many insights, the two languages are different beasts, and the thought processes involved are correspondingly different)
Pointers are very easy, once you "get" them. A very good idea when using pointers is to use the "p" prefix notation. For each pointer (level of indirection) add a "p" to the front of your variable name to remind you that it is a pointer:
Vehicle vehicle = an actual vehicle
Vehicle *pVehicle = a pointer to a Vehicle
Vehicle **ppVehicle = a pointer to a pointer to a Vehicle
To access the vehicle you have to dereference once for each pointer, i.e:
vehicle.SetName("Ford Focus"); // Directly access an object instance
(*pVechicle).SetName("Ford Focus"); // Dereference once
(**ppVehicle).SetName("Ford Focus") // Dereference twice
There are three ways to dereference (just different syntaxes that generate identical code):
(*pVehicle).DoSomething()
pVehicle->DoSomething()
pVehicle[0].DoSomething()
When you use arithmetic on pointers they operate in Vehicle units, not in bytes, i.e
pVehicle++; // Move to the next vehicle record, not just the next byte
And finally, for each
pVehicle = new Vehicle
you need to balance your code with:
delete pVehicle;
pVehicle = NULL;
(edit) Oh, and almost forgot the most important one: ALWAYS check that your pointer is valid before you try to use it!
if (pVehicle != NULL)
...use pVehicle
I find the "p" notation invaluable as you never forget that something is a pointer, and the number of p's tells you how many dereferences are needed. Once I adopted it, I stopped writing NULL dereference/access violation bugs.
That's all you need to know about pointers. Now you just have to use them a lot to gain fluency.