3 ms·
As usually in C, you start from the name, then try to go to the right until you hit parenthesis, then go to the left until parenthesis, rinse and repeat. So, f
by akavel 12y ago
As usually in C, you start from the name, then try to go to the right until you hit parenthesis, then go to the left until parenthesis, rinse and repeat.
So, first, the name:
memset_ptr
Then, try going to the right, but aha! before we can really gain speed, a parenthesis is immediately blocking us. We shrug off the bruises and turn to the left:
(* const volatile memset_ptr)
"Hey guys, memset_ptr is a volatile const pointer..." Now, we hit left parenthesis, so we're again allowed to go right, yay!...
(* const volatile memset_ptr)(void *, int, size_t)
"...to a function taking such-and-such arguments..." Uh, oh, the equal sign, so no more to read to the right; disappointed, we turn back to the left for the final run:
static void * (* const volatile memset_ptr)(void *, int, size_t)
"...returning a pointer to void! Hah, got you! Simple, really. No arrays, no pointers to pointers, not even a function pointer returning a function pointer, meh. Uh, oh, aaaaand, yes, by the way, the variable is static, so, like, file-local, um. Yeah, yeah, I saw it from the beginning, oh, go away, you're just picky. And, and, you wouldn't recognize a function returning a pointer to an array of pointers to functions returning anonymous struct even if it hit you in the face, pfff!"
- neilxdsouza 12y agoThis technique is described in Peter van der Linden's book "Expert C Programming : Deep C Secrets" (and also explained really well by you).
- StavrosK 12y agoIs "void *" really something you can pass?
- deleted 12y ago[deleted]
- joelangeway 12y agoYes, it refers to a memory location, without implying anything about the semantics of the bits located at that location. You can't dereference or assign to the location because you don't know the type at that location. You can however assign that pointer to a typed pointer variable to actually read or write to that memory location. This is useful when you really care about the bits of memory but you're variable pointing to that memory could just as well be an (int64_t ) as a (char ) and those types are not interchangeable with each other, only with (void ). So library functions that just care about memory locations, not the semantics of the bits there, take (void ). Some of this may be technically incorrect. This is my own mental model of the C language which is sometimes incomplete.
- StavrosK 12y agoHmm, I'm a bit confused. Isn't that a function call, rather than a function declaration? If it's a function call, it's passing a bunch of types in, which I thought was not valid C?
- akavel 12y agoAh, now I get your question. So, it is a function declaration, not a function call. Um, sorry: a declaration of a pointer to a function, where this function would take as arguments: some (unnamed) void pointer, some (unnamed) int value, and some (unnamed) size_t value; and would return a void pointer. Um; then there's the equal sign, so this is not only a declaration, but a definition too; but definitely not a call. A call is further down in the original blogpost, in the below line: (memset_ptr)(p, 0, len);
- StavrosK 12y agoOh! A pointer to a function! Aha, I didn't know that was valid, thanks!
- akavel 12y agoI'd say it may be somewhat helpful to realize, that both "void" and " void * " are kinda wild cards in C's type system; they are there, but they're "breaking the rules". And " void * " is not exactly the same to "void", as " char * " is to "char".