How Do I Declare a Function Pointer in C?
fuckingfunctionpointers.com
fuckingfunctionpointers.com
I'm not afraid to admit: I need tools. I need lots and lots of tools to do my job. The more the computer can be used to make my job easier, the better. There is no virtue in hard work for hard work's sake.
Is he wrong in this instance or our you going to ignore his point because he's not always right?
> I'm not afraid to admit: I need tools. I need lots and lots of tools to do my job. The more the computer can be used to make my job easier, the better. There is no virtue in hard work for hard work's sake.
So, as a C programmer I use lot's and lot's of tools. But that doesn't change the point that many view typedefs as bad practice[1].
[1]: http://stackoverflow.com/questions/3781932/is-typedefing-a-p...
Specifically he's talking about typedef'ing structs to a named type to hide that it's a struct. That's different from typedef'ing a function pointer so that you don't need to be a C parsing expert to read the code.
If you can't read C code you should work on your C programming ability, there is nothing difficult about reading function pointers.
Edit: If people are getting tripped up with basic syntax good luck with the actual hard parts of C, Like lack of memory safety, concurrent memory management, undefined behavior, etc.
No need to use typedef, just use an opaque struct if you want something to behave like a blackbox.
double (*my_function(int(*callback)(void*)))(double);
without needing to think way harder on it than if typedefs were used: func2* my_function(func1*)
This isn't basic syntax. C's parser is really bloody complex. That's why we have things like ioccc.org, because C's syntax is NOT trivial.For instance if you need to add an extra parameter, you can easily find all usages. If something else uses the same definition, but is used for a different purpose, it gets much harder to distinguish the different usages. especially for a good ol void (callback)(void context) which a number of event's may use, and then later some may callback with more information which can be changed in once place and the compiler will quickly show you what breaks.
And as mentioned, there _are_ exceptions. Some types just get _sooo_
complex that it's inconvenient to type them out, even if they are
perfectly regular types, and don't depend on any config option. The
"filldir_t" typedef in fs.h is such an example - it's not really opaque,
_nor_ is it a config option, but it sure as hell would be inconvenient for
all low-level filesystems to do
int my_readdir(struct file *filp, void *dirent,
int (*filldir)(void *, const char *, int, loff_t,
u64, unsigned))
{
...
}
because let's face it, having to write out that "filldir" type just made
me use two lines (and potential for totally unnecessary tupos) because the
thing was so complex. So at that point, using a typedef is just common
sense, and we can do
int my_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
...
}
instead.
But it's really quite hard to make that kind of complex type in C. It's
almost always a function pointer that takes complex arguments. typedef int func(void);
func *func_ptr;
Avoids the mess of the function pointer syntax, but still makes the fact that it is a pointer clear.Do you remember where you picked this up? Any particular book or codebase?
Given that, what's the advantage for "your version" of the idiom?
(This may just be nitpicking.)
Pros: beginner confusion; sometimes bugs.
Cons: one less character to type; sometimes able to get more out of a macro
typedef double binary_operation(double, double);
binary_operation add, subtract, multiply, divide;
double add(double a, double b) { return a + b; }
/* ... */
struct binary_operator {
char const *name;
binary_operation *operation;
} binary_operators[] = {
{ "+", add },
{ "-", subtract },
{ "*", multiply },
{ "/", divide },
{ NULL, NULL },
};
You can also use the function type in parameter lists, but it’s equivalent to a function pointer type. int atexit(void function(void)); typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
Without the typedef, it's much less clear.Edit: It could instead be written as the non-pointer type:
typedef void (sighandler_t)(int);
And then used as: sighandler_t *signal(int signum, sighandler_t *handler);
And as a function declaration: sighandler_t foo;
With the pointer in the typedef, the type can't be used to declare functions. typedef int func(void);
/* These two lines are equivalent */
func foo;
int foo(void);
Obviously though, the above is of limited usefulness. It is kinda handy to ensure functions are compatible with a certain typedef, but if it isn't you'll generally see warnings or errors in other locations anyway.The advantage of my technique here is that it doesn't 'hide' the pointer inside of the typedef, which I consider poor form. Consider these two:
typedef int type1;
typedef int type2(void);
typedef int (*type3)(void);
type1 *var1;
type2 *var2;
type3 var3;
type3 *var4;
All of the above are actually pointers, but from the declaration alone you can't tell that `type3 var3` actually declares a pointer. In fact, `type3 var3` and `type2 * var2` declare the exact same thing (minus the name), but `type2 * var2` makes it clear that `var2` is a pointer and not a value type. I find this to be a fairly nice aide in reading, and if you keep this consistent for all types then you don't ever have to worry about a pointer being hidden, or the usage not matching the declaration (IE. You declare it as `type3 var3` but then do something like `* var3`, which looks incorrect unless you know `type3` is actually a pointer).Moreover, lots of people that are newer to C (and even those that aren't but just aren't clear or didn't fully check what `type3` is) will attempt to use `type3 * var`, a double-pointer to a function, when what they really want is `type3 var`, a pointer to a function. There's no confusion over what it is if you don't hide the pointer in the first place, and there's really no great reason to hide it besides not knowing you can avoid hiding it in the first place. Even when you're not new to C, keeping track of things when people do `typedef struct foo * bar` and then `bar * foo2` can get to be a headache really fast.
Edit: Fixed formatting
BUT since ANSI C you can call a function pointer directly: you no longer have to write (*fptr)(arg).
So there is automatic invisible conversion in both directions.
That said, it is possible to see that the function name itself decays into a pointer and isn't a pointer itself. `sizeof(function)` does not return the size of a function pointer, but `sizeof(fptr)` does.
Interesting, function-pointers have the property that they deference to themselves. So `fptr` and `* fptr` are the same thing, as is `* * * * * * fptr` (And also `&fptr`). And since they are the same thing, the `(* fptr) (arg)` syntax works as expected. Personally, I actually prefer to use the `(* fptr) (arg)`, simply because it makes usage of a function pointer clear, but the * really is unnecessary so the benefits are debatable.
The `(* fptr) (arg)` syntax also keeps the "declaration follows usage" pattern intact, since function pointers have to be declared using the * .
And it works with C Blocks!
typedef int IntegerProcessor(int);
int executeTheFunctionPointer(IntegerProcessor* function)
{
return function(23);
}
int executeTheBlock(IntegerProcessor^ block)
{
return block(32);
}
int doubler(int a)
{
return a * 2;
}
int main(int argc, const char * argv[])
{
IntegerProcessor* myFunctionPtr = &doubler;
int a = executeTheFunctionPointer(myFunctionPtr);
printf("%d\n", a); // 46
IntegerProcessor^ myBlock = ^(int b) {
return a * b;
};
a = executeTheBlock(myBlock);
printf("%d\n", a); // 1472
return 0;
}
My mind is completely blown. IntegerProcessor^ myBlock = ^(int b) {
return a * b;
};
I wasn't aware C supported nested functions.Probably, you can't use it.
https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html
But it's not a proper closure, and it's not GC'd, so it's pretty useless.
I'm not 100% sure what you mean by "proper closure" but it does capture variables from the outer scope. It has limitations with scopes and lifetimes, of course.
C doesn't have a type for that, it only has function pointers, which only have space for a single pointer. So what GCC does is actually a horrible hack - it dynamically creates a function (called a trampoline), which calls the actual function with a pointer to its data. But because GCC doesn't have true closures, and only refers to the surrounding function's existing stackframe, which is on the stack, not the heap, this only works until the surrounding function has returned. And since the trampoline is also allocated on the stack, this requires the stack to be executable, which is Not Great for security.
> So what GCC does is actually a horrible hack - it dynamically creates a function (called a trampoline), which calls the actual function with a pointer to its data.
Well you can call it a horrible hack but it's pretty clever. There's no other way to do this without having a rich runtime system and a language with a built-in concept of a heap (and perhaps a garbage collector).
> And since the trampoline is also allocated on the stack, this requires the stack to be executable, which is Not Great for security.
Yeah - this is pretty nasty. Executable stack is less than useful, although it's not enough to protect against stack/buffer overflow exploits that utilize ROP or other advanced attack methods.
However - in my practical experiments, I have noticed that the optimizer will get rid of most trivial trampolines if the resulting function pointer isn't stored or passed to a function in a foreign translation unit. LLVM in particular is really good in eliminating trampolines.
I wish there was a way to have compile time certainty that no trampolines ever get emitted on the stack. You could still use capturing nested functions with certain limitations.
But yeah - it's not the most useful feature, primarily because it's GCC only and secondarily because, at worst, you'll end up executing a few bytes of machine code from the stack.
For example, if you typedef a callback type like so:
typedef int callback_t(int foo);
And then declare a callback like so: callback_t my_callback;
And then later define the callback like so: int my_callback(int foo) {
...
}
The compiler will produce an error if you screw up the function signature of my_callback() when defining it because it won't match the prototype you defined via the typedef. This only works in C. C++ allows multiple function signatures for the same function name, so you probably won't get a compiler error--though you'll likely wind up with a linker error.Edit: The downside is that function declarations done this way will look a little odd--possibly mistaken for a variable definition. And, upon further thought, I'm not sure that this pattern really is a huge benefit since function pointer assignment will also produce an error if the signatures don't match. But interesting nonetheless, I guess.
mentions replacing function declarations for
void (*get_func_on(int i))(int);
with auto get_func_on(int i) -> void (*)(int);
which looks a lot more readable to me. auto get_func_on() -> std::function<void(int)>More specifically, std::function's operator() is virtual, and calls into a subclass that's specialized to function pointers of type void(int). The subclass then performs the actual function pointer call.
This can be virtual functions, or, more commonly, an hand rolled vtable. In the last case, if std::function is constructed with a function pointer exactly matching its signature it could in principle avoid the thunk and directly point to the function itself. I don't think most implementations bother.
/pedantic
Also this comment by Linus Torvalds (copy pasted because I don't know how to link to Google+ comments):
> I don't think that works. It breaks trivially for consecutive [] or * cases, something that he carefully didn't have in his examples.
> So the examples were made up to make it look like it's a spiral, but type parsing is about precedence, not about spirals. It so happens that the higher-precedence operators ([] and ()) are on the right-hand side, which is why it "works" to start on the right.
> And it doesn't explain why
> typedef int (fn_t[][2])(void);
> is ok, but
> typedef int (fn_t[2][])(void);
> is not.
> "Spirals"? I don't think so.
typedef int *(**fn_t[][2])(void);
is ok, but typedef int *(**fn_t[2][])(void);
is not.(fixed formatting?)
See also my comment last time this subject came up: https://news.ycombinator.com/item?id=12775966
int* p; // p is an int pointer
instead of int *p; // dereferencing p will give an int
I know this is the subject of holy wars, but once I'd seen the second one my eyes were opened and I had way less trouble. I think that declaration follows use is another of example of the amazing design powers of the patriarchs.Thanks for elevating their gender specifically.... gosh forbid that Ada had any amazing design powers.
Given the almost certainty (in my mind anyway), that the OP meant no disrespect to people who identify with genders that are not male, it would make me very happy indeed if requests for correction could be made in a respectful way. Simply asking something like "Would you mind using the alternative phrasing 'blah blah blah'" would go a long way towards helping everyone to maintain a civil tone.
> int * const a
? i.e. in what way do you extend your scheme such that it makes sense again?
int * foo, bar;
are variables of two different types, the asterisk clearly has affinity to the variable name. It is misleading to bind it to the base type name.Like, it's tautological: 'de-referencing an int pointer will give you an int'
Brains are weird.
As a variable:
returnType (*variableName)(parameterTypes) = function_name;
variableName is a pointer to a function that accepts parameterTypes and returns returnType As a static const variable:
static returnType (* const variableName)(parameterTypes) = function_name;
variableName is a const pointer to a function that accepts parameterTypes and returns static returnType (or maybe variableName is the static thing?) As an array:
returnType (*arrayName[])(parameterTypes) = {function_name0, ...};
arrayName is an array of pointers to functions that accept parameterTypes and return returnType As an argument to a function:
int my_function(returnType (*argumentName)(parameterTypes));
my_function is a function that accepts an argumentName, which is a pointer to a function accepting parameterTypes and returning returnType, and returns an int As a return value from a function:
returnType (*my_function(int, ...))(parameterTypes);
my_function is a function that accepts int and other parameters and returns a pointer to a function that accepts parameterTypes and returns returnType As a typedef:
typedef returnType (*typeName)(parameterTypes);
a typeName is now a pointer to a function that accepts parameterTypes and returns returnTypeI'm actively working on the page. Once it stabilizes, I'll consider mirroring a sanitized version instead of using the "stealth redirect".
http://goshdarnfunctionpointers.com is a more work-friendly mirror.
which states:
Unable to access this site due to the profanity in the URL?
http://goshdarnfunctionpointers.com is a more work-friendly mirror.
which is a possibly an offending link to itself. But, there is also possibly the more benignly named:
T x; T *y;
T f(); T (*g)();
T pointer to T
function returning T pointer to function returning T
and the alternative, T h(); , is parsed as T (h()); and thus becomes "function returning pointer to T".The apparent struggle I see with this syntax has always somewhat puzzled me, because I don't see the same level of complaints about e.g. arithmetic expressions (like 6+3*4/(2+1)) which are parsed with precedence in much the same way. K&R even has a section on writing a parser that recognises this syntax, so I suspect it's really not that hard, but the perception spread by those who didn't learn the syntax but only memorised the "easy cases" is making it appear more difficult than it really is.
int *a -> expression *a has type int.
int *a[10] -> *a[_] has type int.
int (*a)[10] -> (*a)[_] has type int.
int (*a)(int, int) -> (*a)(_, _) has type int.
No need for complicated things like "spiral rules", etc.It looks like what they did was take the syntax from B:
auto x[10];
and generalize it such that the type name ended up before the variable name, as in Algol. But in B this worked much better, because it didn't have array types (or pointer types, or function types) - everything was a machine word. So [] in a variable declaration was just to allocate memory to which the variable would refer; the variable itself would still be a word. When they made [] part of the type, and added pointers and function types, the result was a mess. char const *(* const (*(*ip)())[])[]
are trivial to read? [Read this](http://www.icce.rug.nl/documents/cplusplus/cplusplus03.html#...) and you'll never struggle with any declaration ever again.No it doesn't:
p += k[foo(bar, baz, 3*(quux+1))] << 32-m[++i];With name-first declaration syntax (Pascal, Modula, Go, Rust), parsing is context-independent again. Readability improves. Error messages improve. Syntax-coloring editors with a single-file view don't get lost.
a (b); /* function call or declaration */
a * b; /* multiplication or declaration */
f((a) * b); /* multiplication or deref and cast */
> With one further change, namely deleting the production typedef-name: identifier and making typedef-name a terminal symbol, this grammar is acceptable to the YACC parser-generator.[1] http://eli.thegreenplace.net/2007/11/24/the-context-sensitiv...
template<size_t N = sizeof(void*)> struct a;
template<> struct a<4> {
enum { b };
};
template<> struct a<8> {
template<int> struct b {};
};
enum { c, d };
int main() {
a<>::b<c>d;
d;
}
Depending on which instantiation is used, the first line of main is either a variable declaration, or two operators < and > applied in sequence.This is especially fun to deal with for C++ IDEs that support semantic highlighting (i.e. typenames are in a different color etc). If I remember correctly, the first one that could handle this right was VS 2012 - it only took 14 years after ISO C++ standard was released...
It was not a successful idea, but there was a method to the madness.
template <typename Func> using function_ptr = add_pointer_t<Func>;
and now declarations are a bit more sane: void foo(function_ptr<void (int)> callback); typedef void function_ptr_t(int i);
function_ptr_t* ptr; #define INT_PTR int*
INT_PTR p, q;
the code is actively misleading. Is there a better way to do it for function pointers? auto greet = std::mem_fn(&Foo::display_greeting);
Looks pretty simple to me, much simpler than C function pointers. :)Pairs nicely with std::bind, too, like so:
Foo foo;
std::function<void(int)> setter = std::bind(&Foo::setValue, &foo, std::placeholders::_1);
setter(42);And std::function introduce some performance overhead.
Trivially solved with decltype, no need to remember anything.
decltype(std::mem_fn(&Foo::Whatever))
Typedef it if you want.
> And std::function introduce some performance overhead.
It's the same performance as a virtual function call. Pretty much the same as a function pointer invoke.
void foo(std::function<void(int)> callback); return_type Fn(parameters) var;
typedef return_type Fn(parameters) TypeName;
where Fn is a new keyword -- or not, if compiler understands dummy syntax -- (I would suggest λ when using greek letters in code become norm).It simplifies the C syntax a lot IMHO.
PS: now I am out-of-the-box, maybe this is better:
Fn{return_type, param1, param2} *var;