When I first started working with them, the biggest problem I had was the syntax.
int* ip;
int * ip;
int *ip;
are all the same.
but:
int* ip1, ip2; //second one isn't a pointer!
int *ip1, *ip2;
Why? because the “pointer” part of the declaration belongs to the variable, and not the type.
And then dereferencing the thing uses a very similar notation:
*ip = 4; //sets the value of the thing pointed to by ip to '4'
x = ip; //hey, that's not '4'!
x = *ip; //ahh... there's that '4'
Except when you actually need to get a pointer… then you use an ampersand!
int *ip = &x;
Hooray for consistency!
Then, apparently just to be jerks and prove how clever they are, a lot of library developers use pointers-to-pointers-to-pointers, and if they expect an array of those things, well why not just pass a pointer to that too.
void foo(****ipppArr);
to call this, I need the address of the array of pointers to pointers to pointers of ints:
foo(&(***ipppArr));
In six months, when I have to maintain this code, I will spend more time trying to figure out what all this means than rewriting from the ground up.
(yeah, probably got that syntax wrong — it’s been a while since I’ve done anything in C. I kinda miss it, but then I’m a bit of a massochist)