void * (*proto_type(long int, char *b)) (const char *b, unsigned short int d);
The return type is void* and proto_type is the name of the function? Or is this a pointer to function? Which are the parameters:
(long int, char *b)
or this (const char *b, unsigned short int d)
Please, explain how this function works.
Parameters are specified within the pair of parentheses in the function definition, separated by commas. When we call the function, we supply the values in the same way.
For example, if one defines a function as def f(x): ... , then x is the parameter, and if it is called by a = ...; f(a) then a is the argument. A parameter is an (unbound) variable, while the argument can be a literal or variable or more complex expression involving literals and variables.
A parameter is the variable listed inside the parentheses in the function definition. An argument is the value that is sent to the function when it is called.
Parameter values to functions are stored on the stack as well, pushed immediately before the return address. Everything what lives on the stack (local variables, parameters etc.)
void * (*proto_type(long int, char *b)) (const char *b, unsigned short int d);
This is a function declaration. The function name is proto_type
, which takes two parameters of types:
long int
char *
and returns a pointer to a function which takes
const char*
unsigned short int
and returns void*
.
Now if you use typedef, all of the above will becomes obvious:
typedef void* function_type(const char *b, unsigned short int d);
function_type* proto_type(long int, char *b);
Hope that helps.
This declares proto_type
as function taking (long int, char *)
and returning pointer to a function taking a (const char *, unsigned short int)
and returning a void pointer.
In other words:
typedef void * (*R)(const char *, unsigned short int); // return type
R proto_type(long int, char *);
I suggest bookmarking www.cdecl.org for the questions of this type. Beware, the page is a bit picky about what you type in (it doesn't accept parameter names at least).
Start with the name of the function, then evaluate that using the usual expression syntax. Thus:
proto_type // proto_type
proto_type( long, char* ) // is a function taking long, char*
// (since function call has precedence over *
*proto_type( long, char* ) // returning a pointer
(*proto_type(...)) // (no change, but necessary for precedence reasons)
(...)( char const*, unsigned short )
// to a function taking char const*, unsigned short
*(...)(...) // returning pointer
void *(...)(...) // to void
(It's a little harder in cases where you don't have the name,
like the type in a static_cast
.)
I will explain my process for parsing complex c-style declarations. I hope you will find it useful.
C-style parsing can be thought of as a right-to-left parsing starting at the identifier and bounded by parenthesis. So we start at the identifier proto_type
// vvvvvvvvvv-------------------
void * (*proto_type(long int, char *b)) (const char *b, unsigned short int d);
As we can see, moving right from proto_type, we immediately see a function call and some parameters, so that's easy. proto_type
is a function that takes a long int
and char*
as parameters.
// v
void * (*proto_type(long int, char *b)) (const char *b, unsigned short int d);
Here we hit the first bounding parentheses, so we have to go backwards to find the next token which is here:
// v----------------------------
void * (*proto_type(long int, char *b)) (const char *b, unsigned short int d);
So now we know it returns a pointer to something. Now we have to look to the right again to find out what because of the bounding parentheses again
// v--------------------------------vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
void * (*proto_type(long int, char *b)) (const char *b, unsigned short int d);
Since we found another function call operator, the pointer it returns must be a pointer to a function that takes a const char*
and an unsigned short int
.
Finally, we reached another bounding parentheses, so move back left to find the return value of that function pointer.
//vvvv----------------------------------------------------------------------v
void * (*proto_type(long int, char *b)) (const char *b, unsigned short int d);
The function pointer returns a void* as the return value.
So to recap in English: proto_type
takes a long int
and a char*
as parameters and returns a pointer to a function that takes a const char*
and unsigned short int
as parameters and returns a void*
.
proto_type
is a function, which takes two arguments, long int
and char *
. It returns a function pointer that takes two arguments of type const char *
and unsigned short int
.
And to write this without using typedef is not very kind to the reader.
Using VS2012 on Windows 8 x64.
proto_type
is a function that takes a long int
(which is unnamed) and an unsigned short int d
, and returns a function of the form void * proto2(const char *b, unsigned short int d);
Here's some working code:
#include <stddef.h>
void * (*proto_type(long int, char *b)) (const char *b, unsigned short int d);
void * proto2(const char *b, unsigned short int d);
int main(int argc, char** argv){
if(proto_type(0, NULL)(NULL, 0) != (void*)8675309)
return 0;
else
return 1;
}
void * (*proto_type(long int, char *b)) (const char *b, unsigned short int d){
return &proto2;
}
void* proto2(const char *b, unsigned short int d){
return (void*)8675309;
}
What's going on is that main
calls proto_type
which returns a pointer to proto2
, which main
immediately calls. proto2
returns a magic pointer value that we check against in main
.
Here's the debug output from VS2012:
The program '[3188] test.exe' has exited with code 1 (0x1).
As for "how this function works", the answer is however you want it to (assuming you're the one implementing it).
If you want another way to look at it, you want to read it inside to out for the order of which functions are called.
The lesson here is that C(++) function pointers are immensely opaque.
I have done what @Tomek said and copied your prototype to http:www.cdel.org and then removed the parameter names from the prototype as:
void * (*proto_type(long int, char *)) (const char *, unsigned short int );
pressed enter, and the web site returned:
declare proto_type as function (long int, pointer to char) returning pointer
to function (pointer to const char, unsigned short int) returning pointer
to void
Now, to translate this into carbon-unit speak: proto_type is declared as a function that takes a long int
and a pointer to a char
as parameters, it returns a pointer to a function that takes a pointer to a const char
and an unsigned short integer
and that function returns a void pointer
.
Finally, a void pointer
can be cast into a pointer to any other data type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With