7 ms·
Basics Of Function Pointers In C
- ColinDabritz 13y agoGood examples and great 'blow by blow' breakdown. This is a really tough concept to learn, and the C syntax gets a little complicated. This was well laid out, readable, and had a good progression of concepts. Well done!
- mathattack 13y agoThis was one of the toughest things for me to learn in C. I think I had to learn it 3 times before it stuck. As more schools depart from teaching C, it's worthwhile to have simple explanations.
- null_ptr 13y agoI remember fondly the time when I learned to use C function pointers. They really stepped up my code design :-)
- ChuckMcM 13y agoNow it just needs the matching tutorial on initializing pointers in the data section :-)
- null_ptr 13y agoCould you please elaborate?
- angersock 13y ago(fitting user name, sir or madam!) I'm guessing he's referring to declaring a global structure or collection of function pointers, and then using #ifdef's and compiler flags to actually assign those function pointers to things that make optimal sense for the architecture. Or, at runtime (but hopefully before usage!) setting those global function pointers to point at routines optimal for the situation the program is running under--say, setting them to point at an optimized SSE3 vector routine if the CPU supports it. Maybe that's it?
- ChuckMcM 13y agoJust the other day I was looking at some embedded SoC which had some data structures for setting up various GPIOs and pins and such, it was something like: struct gpio_config { uint8_t func; uint8_t options; uint32_t *loc; }; struct gpio_alloc { struct gpio_config pins[4]; struct gpio_alloc *next; }; struct gpio_alloc fsmc_1 = { ... }; All the pre-initialization stuff (which was being stored in flash so it was really read-only data) was code I realized not a lot of people wrote in C these days.
- angersock 13y agoUnderstanding function pointers in C unlocks the ability to write clean, object-oriented code with inheritance (kinda, sorta, shhhh). With great power, etc. etc.
- adambard 13y agoI committed what I now realize were true crimes against software engineering when I first learned of function pointers.
- spc476 13y agoThey can't be any worse than abusing the C preprocessor to implement templates for C code (a sin I committed in college).
- aktau 13y agoSometimes it is a useful sin, many data structure libraries for C use this for: 1) genericity 2) (extreme) speed It's (unfortunately) impossible for C to equal C++ templates in this: write once, use for multiple datatypes (without macros). For people who like copy pasting, generic macros is on the horizon for C11, which is rapidly being implemented (and mostly works) for Clang and GCC, the most important compilers. Read more about it here: http://www.robertgamble.net/2012/01/c11-generic-selections.html http://www.robertgamble.net/2012/01/c11-generic-selections.h... Simply put, it allows to create a small "shim"-macro that detects the type of the input parameters and redirect to an actual function based on type.
- roel_v 13y agoWhat's wrong with that? It allows you to write type-safe sort-of-generic data structures. It's certainly better than 'generic' data structures that work on void*'s.
- yk 13y agoYou mean as in func(foot); /* Should check func != gun.shoot */
- 13y ago
- greenyoda 13y agoThe article is missing at least one useful thing: how to declare a typedef for a function pointer. This can be used both to avoid error-prone duplication of declarations and to simplify excessively complex declarations. Here's a simple example: http://en.wikipedia.org/wiki/Typedef#Using_typedef_with_function_pointers http://en.wikipedia.org/wiki/Typedef#Using_typedef_with_func... Here's a more complex example: http://www.devx.com/tips/Tip/13829 http://www.devx.com/tips/Tip/13829 Here's a tutorial on how to interpret the complex declarations like the one at the top of the previous example: http://www.codeproject.com/Articles/7042/How-to-interpret-complex-C-C-declarations http://www.codeproject.com/Articles/7042/How-to-interpret-co... Here's a discussion about using typedefs for function pointers on StackOverflow: http://stackoverflow.com/questions/1591361/understanding-typedefs-for-function-pointers-in-c-examples-hints-and-tips-ple http://stackoverflow.com/questions/1591361/understanding-typ... See also: The Linux command "cdecl": http://linux.die.net/man/1/cdecl http://linux.die.net/man/1/cdecl Plus, there's an on-line version: http://www.lemoda.net/c/cdecl http://www.lemoda.net/c/cdecl
- deleted 13y ago[deleted]
- buttproblem 13y agoThe most useful education I got on reading function pointers is the spiral rule: http://c-faq.com/decl/spiral.anderson.html http://c-faq.com/decl/spiral.anderson.html (I accidentally deleted my reply)
- conradev 13y agoIt's also good to note that these links for further reading are applicable for blocks in Objective-C, which use the same syntax for declaration, only replacing the asterisk '*' with a caret '^'.
- yuvadam 13y agoThere's another interesting discussion here: http://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work/ http://stackoverflow.com/questions/840501/how-do-function-po...
- Radle 13y agoBut why that whole mess with function pointers? Where do they have the key advantage compared to directly calling the function?
- dllthomas 13y agoIf you need to determine which function to call dynamically, in an extensible way. Take a signal handler or other callback. There are more sophisticated uses, but that seems a clear and straightforward example.
- asveikau 13y agoLet's look at the signature of qsort() from libc: void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); qsort is a function inside of libc.so. It's already been compiled. It doesn't know about the "compar" pointer you're going to pass it. That function might not even exist yet. qsort doesn't know if you're sorting integers, sorting strings, sorting struct foo which is still being ironed out. It knows how to sort arrays. You give it the size of each element, the number of elements, and a function pointer that it will call to compare elements. It will call you back and you can stick your data-structure-specific knowledge into that function. (This turns out to be a lousy way to sort arrays, by the way. If you used a C++ template instead, the comparison function could be inlined directly in the sort algorithm, which gives you better object code. But you lose the possibility that the caller and callee exist in different modules, for example.)
- Radle 13y agothanks, that helped me out <3
- exDM69 13y ago> qsort is a function inside of libc.so. It's already been compiled. Unfortunately, this is also why it is so damn slow. Try comparing C++ std::sort with C qsort, the performance gap is HUGE. The reason is that the "function pointer" std::sort gets inlined but qsort will actually invoke a function call via function pointer. If you'd move qsort to a header file as an inline function, the performance problem would go away.
- deleted 13y ago[deleted]
- cjh_ 13y agoVery well written article, clearly explaining what is usually a rather complex topic for new programmers to understand, bookmarked for future use. The other resource I use for similar situations is http://c-faq.com/decl/spiral.anderson.html http://c-faq.com/decl/spiral.anderson.html [EDIT]: someone beat me to it FWIW: The explanation by Dave G in the comments isn't quite right (I couldn't reply there, comments appear closed): > void something(); // prototype of function that takes undetermined number of arguments > void something(void); // prototype of function that takes no arguments > void something() { return; } // function that takes no arguments isn't quite right as `void something(){ return; }` is still a function that takes an undetermined number of arguments, it just cannot access them; calling `something(1,2,3)` is still valid. > void unknown(){ return ;} > int main(void){ something(1,2,3);} is valid.
- lubomir 13y agoNice summary. However, the comment about first example is slightly inaccurate. Saying the `sayHello` function does not take arguments is wrong. It does, it just does not care about them. You could still call it with arguments like sayHello("world", 15) and there would be no compiler warning nor error. If you want to declare a function with no arguments, just do it as `sayHello(void)`. Then, the previous example would result in compile-time error.
- fnayr 13y agoUpdated with that info from the comments already
- adam-f 13y agoPsha, try pointer-to-member-functions in C++. I wrote a fluent reflection/serialization engine a while back which made heavy use of them. https://github.com/sparecycles/reflect/blob/master/include/reflect/property/AccessorAccessProperty.hpp#L63 https://github.com/sparecycles/reflect/blob/master/include/r...
- icantthinkofone 13y agoThis is C, not C++.
- felxh 13y agoIf the name of a function is already the memory address of the function, what extra information does the pointer store? Couldn't you just assign the name of the function to, say, an int?
- vidarh 13y agoYou can coerce it to an int with a cast, with some caveats: It is implementation defined whether or not the size of an int is sufficient to store a pointer, and the type lets the compiler know what you want to happen when you operate one it. If "foo" is an integer variable, then "foo + 1" returns the integer value of foo + 1, but if "foo" is a pointer, "foo + 1" returns the value of foo + the size of a pointer, for example. So the pointer does not store any extra information, but the compiler stores and makes use of extra information about the pointer variable (not about the value itself) during compilation.
- felxh 13y agoThat makes a lot of sense, thanks!
- emillon 13y agoYou can, but it makes more sense to assign it to a void \*. After all, it's a pointer but you don't know the size of the pointed object. Note: this is not true everywhere since (data) pointers and function pointers can be represented differently, but on a PC it works :)
- artagnon 13y agoOn a related note, a teaching aid I wrote out for my classmates in high school: http://artagnon.github.io/authored/cs-pointers.pdf http://artagnon.github.io/authored/cs-pointers.pdf
- kadaj 13y agoThis is a simple explanation of the basics of pointers to function.
- lsiebert 13y agoA good basic article. An advanced article would talk about arrays of function pointers, pointers to function pointers, returning function pointers and so on. It can get pretty crazy looking.
- throw7 13y agoI've always liked the presentation of the "spiral rule" at this page: http://www.unixwiz.net/techtips/reading-cdecl.html http://www.unixwiz.net/techtips/reading-cdecl.html
- apaprocki 13y agoFunction pointers are a great tool for untangling balls of code and level-izing different components based upon dependencies in a large project. Rather than having to wait until all code is logically refactored, you can poke function pointers to higher-level functionality down into lower-level libraries to remove the physical link-time dependency and/or circular dependency loops. There are other tricks you can use if your higher-level code is written in C++. You can take advantage of static initializers to do your function pointer poking for you instead of having to manually do it all in main() or some other point of initialization, potentially creating other physical dependencies. (As long as no other static initializers depend on the function pointers being in place, because order of execution is not guaranteed.) e.g.: extern "C" { static void higher_level_function_pointer(void) { ... } } namespace { class CallbackLoader { CallbackLoader() { lower_level_library_set_callback(&higher_level_function_pointer); } }; static const CallbackLoader loader; }
- adultSwim 13y agoFor decoding types, particularly with function pointers, I recommend learning the right left rule. http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html
- to3m 13y agoThe C syntax really makes this simple feature look terribly complicated. It's a while since I watched them, but in the SICP video lectures, as I recall, the notion of storing functions in variables - as introduced in, like, lecture 1 or 2 - took about 0.1% of the time - if indeed that. And that's because while the principles are actually more complicated than the C example (due to the lexically-scoped variable capture), the syntax is simplicity itself. Consider the issue of making a variable, which goes something like this: (let ((x 1)) (set! x (1+ x))) You have your "let", then the list of names and values, and then the stuff that makes use of them. Now consider the issue of making a function: (let ((x (lambda () (message "stuff")))) (x)) (Well... maybe they called it define. I don't remember.) The parallels are obvious, and indeed I suppose they deliberately chose this notation to emphasise the similarity between one type of value (e.g., an int) and any other (e.g., a closure). And so once you've got the hang of making a function that takes one type of value (e.g., an int), it's a small step from there to making a function that takes another type of value (e.g., a closure). This is a dig at C and its ilk rather than the article. It's ridiculous that such a fundamental, basic primitive is given such a baroque syntax. But then C strikes me as designed for people who already know how to program so maybe the assumption is that most users will already know what function pointers are when they come to it, probably from being familiar with indirect jumps in assembly language. This post is apropos of very little, I guess. I was just moved to comment after seeing six pages of stuff that still never got to the meat of the matter. So I suppose I should finish it like this: "</rant>"
- qu4z-2 13y agoI think the only complicated-looking thing in C is the syntax for declaring function pointer types. If you use typedefs you end up with typedef int (*math_op)(int, int); math_op ops[] = { add, subtract }; int a = ops[0](3, 5); int b = ops[1](9, 2); ... maybe I've just used them too much, but I find them quite simple (except, as mentioned, setting up the initial typedefs which is a bit "odd"). One of my favourite uses of function pointers is for key-mappings, like in: https://github.com/muennich/sxiv/blob/master/config.def.h https://github.com/muennich/sxiv/blob/master/config.def.h
- millerm 13y agoThanks for the link. I will pass this onto other developers I know who have trouble understanding this topic. I recently read this book and it's the best book I've ever read about pointers in C: Understanding and Using C Pointers Core techniques for memory management By Richard Reese Publisher: O'Reilly Media Released: May 2013 Pages: 226 http://shop.oreilly.com/product/0636920028000.do http://shop.oreilly.com/product/0636920028000.do