What is use of function pointer

Thread Starter

anukalp

Joined Jul 28, 2018
158
Hello,
I'm struggling to understand function pointer, Please see below the attempt I've made so far :

Code:
#include <stdio.h>
int *add(int x, int y);
int main()
{
   int a = 5;
   int b = 4;
   return 0;
}

int *add(int x, int y)
{
    return x + y;
}
What is use of function pointer ?
 

Zeeus

Joined Apr 17, 2019
616
Hello,
I'm struggling to understand function pointer, Please see below the attempt I've made so far :

Code:
#include <stdio.h>
int *add(int x, int y);
int main()
{
   int a = 5;
   int b = 4;
   return 0;
}

int *add(int x, int y)
{
    return x + y;
}
What is use of function pointer ?
Hmm..you can use pointer like this ? Alot to learn

Is there an example you saw cos this code didn't even compile and looks like nothing will be done even if it did

"There is no substitute for hard work. An athlete work hard for 15 years to perform just for 15 seconds!":(:)
 

ci139

Joined Jul 11, 2016
1,989
many
you can use same function header/definition/reference for similar operations applied to different targets
e.g.
• for moving geometric shapes around ← is the best example as to apply same operation for different targets
• to construct buffers or node structures (that may hold different object types)
• apply math operations for different argument data types /// the use of this is highly programming language dependent = varies a lot between different programming languages . . . in javascript 1 possible implementation is Procedure(arg1,arg2) where the value is returned at arg1 having it's type (in other languages - such requires the variables to be defined as object pointers to records with the data fields (VarType , VarPTR or VarValue) )
 
Last edited:

nsaspook

Joined Aug 27, 2009
16,321
Simple old microchip C18 code examples of the function pointer in a motor tester. Each type of motor has it's own display procedure executed from a common display function pointer in a mode structure. Polymorphism/inheritance in OOP terms. Polymorphism/inheritance is not a property of a language, it's a technique to write code. Objects (procedure and data in C) of different types can be accessed through the same interface

typedef void (*display_func)(void);

struct modetype {
volatile uint8_t demos, move, free, operate, demos_init, slow, emo, v24, cal, on_off_only, idle, locked, info_only, qei, slow_bypass, change;
display_func display;
};

// -- various motor configurations defined for each motor type in the program configuration structures

if (part == E220E500_E) {
term_time();
mode.display = e220_qei_display;
putrs2USART("\x1b[7m Init E220E500 QEI MOTOR. \x1b[0m\r\n");
for (z = 0; z < MAX_MOTOR; z++) {
motordata[z].slow = FALSE;
motordata[z].slow_only = FALSE;
motordata[z].active = FALSE;
motordata[z].reversed = FALSE;
motordata[z].v24 = FALSE;
}
motordata[0].active = TRUE; // X motor for assy position
mode.qei = TRUE;
qei1.c = 0; // set motor and set knob to zero counts
knob2.c = 0;
V.qei_counts = 0;
V.pwm4int_count = 0;
}

if (part == V810_MS || part == EV810_MS) {
term_time();
mode.display = v810_ms_display;
putrs2USART("\x1b[7m Init VISTA MASS SLIT. \x1b[0m\r\n");
for (z = 0; z < MAX_MOTOR; z++) {
motordata[z].slow = FALSE;
motordata[z].slow_only = FALSE;
motordata[z].active = FALSE;
motordata[z].reversed = FALSE;
motordata[z].v24 = FALSE;
motordata[z].cal_pos = V810_MS_CAL;
motordata[z].pot.limit_change = V810_MS_CHANGE;
motordata[z].pot.limit_span = V810_MS_SPAN;
motordata[z].pot.limit_offset_l = V810_MS_OFFSET_L;
motordata[z].pot.limit_offset_h = V810_MS_OFFSET_H;
}
motordata[0].active = TRUE; // x motor for SLIT position
}

// ---- various display codes

void v810_ms_display(void)
{
if (help_pos == 0) {
sprintf(bootstr2, " "); // info display data
LCD_VC_puts(VC0, DS1, YES);
sprintf(bootstr2, "%cR%2i Set%2i V%3li I%2li ", Cursor[0], motordata[0].pot.scaled_actual / 10, motordata[0].pot.scaled_set / 10, R.pos_x, R.current_x);
LCD_VC_puts(VC0, DS2, YES);
sprintf(bootstr2, " "); // info display data
LCD_VC_puts(VC0, DS3, YES);
} else {
sprintf(bootstr2, " ");
LCD_VC_puts(VC0, DS1, YES);
sprintf(bootstr2, " ");
if (motordata[0].active) sprintf(bootstr2, "X Pot%3i O%2i S%2i C%2i ", motordata[0].pot.pos_actual, motordata[0].pot.offset / 10, motordata[0].pot.span / 10, motordata[0].pot.pos_change);
LCD_VC_puts(VC0, DS2, YES);
puts2USART(bootstr2);
putrs2USART("\r\n");
sprintf(bootstr2, " ");
LCD_VC_puts(VC0, DS3, YES);
}
}

void e220_qei_display(void)
{
if (help_pos == 0) {
sprintf(bootstr2, "%cR%2li S%2li E%2i ", Cursor[0], qei1.c, knob2.c, motordata[0].pot.error);
LCD_VC_puts(VC0, DS1, YES);
if (motordata[0].run) {
sprintf(bootstr2, " Motor direction %i ", (int16_t) motordata[0].cw); // info display data
LCD_VC_puts(VC0, DS2, YES);
sprintf(bootstr2, " Movement %li ", qei1.band); // info display data
LCD_VC_puts(VC0, DS3, YES);
} else {
sprintf(bootstr2, " "); // info display data
LCD_VC_puts(VC0, DS2, YES);
sprintf(bootstr2, " "); // info display data
LCD_VC_puts(VC0, DS3, YES);
}
} else {
sprintf(bootstr2, " ");
if (motordata[0].active) sprintf(bootstr2, "X Pot%2i O%2i S%2i C%2i ", motordata[0].pot.pos_actual / 10, motordata[0].pot.offset / 10, motordata[0].pot.span / 10, motordata[0].pot.pos_change);
LCD_VC_puts(VC0, DS1, YES);
puts2USART(bootstr2);
putrs2USART("\r\n");
sprintf(bootstr2, " ");
if (motordata[1].active) sprintf(bootstr2, "Y Pot%2i O%2i S%2i C%2i ", motordata[1].pot.pos_actual / 10, motordata[1].pot.offset / 10, motordata[1].pot.span / 10, motordata[1].pot.pos_change);
LCD_VC_puts(VC0, DS2, YES);
puts2USART(bootstr2);
putrs2USART("\r\n");
sprintf(bootstr2, " ");
if (motordata[2].active) sprintf(bootstr2, "Z Pot%2i O%2i S%2i C%2i ", motordata[2].pot.pos_actual / 10, motordata[2].pot.offset / 10, motordata[2].pot.span / 10, motordata[2].pot.pos_change);
LCD_VC_puts(VC0, DS3, YES);
puts2USART(bootstr2);
putrs2USART("\r\n");
}
}

// -- various uses of mode.display The usage of function pointers here reduces the need to hand code different operations for each type of motor in the running code space.

/* assembly selection */
void nav_menu(void) // call the correct screen display function
{
Set_Cursor();
mode.display();

}

/* assembly selection */
void exerciser(void)
{
Set_Cursor();
switch (mode.operate) {
case VIISION_M:
nonqei_exer(2);
break;
case E220E500_M:
nonqei_exer(2);
break;
case E220E500_E:
e220_qei_exer(3);
break;
case GSD_M:
nonqei_exer(2);
break;
case VIISION_MS:
nonqei_exer(2);
break;
case V810_MS:
case EV810_MS:
nonqei_exer(2);
break;
case VARIAN_V:
nonqei_exer(4);
break;
case HELP_M:
mode.display();
break;
default:
mode.display();
break;
}
}

// -- main program loop

/* main HID loop */
void hid_menu(void)
{
static uint8_t menu_pos = HELP_M;

menu_pos = get_hid();
check_cable(&menu_pos);
update_lcd_menu(menu_pos);
nav_menu();
}

/* Loop forever */
while (TRUE) {
ADC_read();
if (emotor_is_all_off() && WORKERFLAG) zero_amploc();
hid_menu();
ClrWdt(); // reset the WDT timer
if (mode.cal) {
run_cal();
menu_pos = get_hid();
check_cable(&menu_pos);
update_lcd_menu(menu_pos);
}
ClrWdt(); // reset the WDT timer
update_hist();
track_motor();
if (mode.idle) {
help_pos = 0;
}
}
 
Last edited:

402DF855

Joined Feb 9, 2013
271
The quicksort in the C standard library is a simple example of a function pointer which is used to compare elements of whatever type is being sorted:
C:
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
The example on Wikipedia sorts an array of integers.
C:
int compare_ints(const void *p, const void *q) 
{
    int x = *(const int *)p;
    int y = *(const int *)q;

    if (x < y)
        return -1; // Return -1 if you want ascending, 1 if you want descending order.
    else if (x > y)
        return 1;   // Return 1 if you want ascending, -1 if you want descending order.
    return 0;
}

/* Sort an array of n integers, pointed to by a. */
void sort_ints(int *a, size_t n) {
    qsort(a, n, sizeof *a, compare_ints);
}
 

ApacheKid

Joined Jan 12, 2015
1,762
Function pointers are very handy, a particularly good use for then is in finite state machines. In this design we have a 2D lookup table and the table stores function pointers.

A outer loop receives some kind of event or signal or whatever and it uses that event ID along with the current "state" ID (just integers) to index into the table and invokes the function that is at those coordinates. The function often (depends on design) returns the new state.

May sound like overkill but if you have more than say five or six events and five or six states and non-trivial processing for each state transition it is a very neat design, the outer loop is pretty simple and each event handler is a well defined function with a common signature and does a simple job.

I've done this several times for compiler and so on on, often debugging becomes little more than verifying that the 2D table is correctly initialized and that each function does return the correct next state, very complex behaviors can be implemented with very high reliability and very easy to read code.

Also as others will no doubt say function pointers are the bedrock of "callbacks" where we call some function and hand it the address of some other function that will get called when some thing happens, UART's for example use this.
 

ApacheKid

Joined Jan 12, 2015
1,762
Here's some useless code that show you what I mean by a table driven FSM (many FSM implementations are switch statements or even nested switch statements - very bad idea but for the most trivial cases).

Code:
#include<stdio.h>
#include<stdlib.h>

typedef int (*Handler_ptr)(int);

int handle_event_0_state_0(int X)
{
    // do stuff
    return 1;
}

int handle_event_1_state_0(int X)
{
    // do stuff
    return 2;
}

int handle_event_2_state_0(int X)
{
    // do stuff
    return 3;
}

int handle_event_3_state_0(int X)
{
    // do stuff
    return 0;
}

int handle_event_0_state_1(int X)
{
    // do stuff
    return 1;
}

int handle_event_1_state_1(int X)
{
    // do stuff
    return 2;
}

int handle_event_2_state_1(int X)
{
    // do stuff
    return 3;
}

int handle_event_3_state_1(int X)
{
    // do stuff
    return 0;
}

int  main() {

    Handler_ptr table[4][4] =
    {
        {handle_event_0_state_0, handle_event_1_state_0, handle_event_2_state_0, handle_event_3_state_0},
        {handle_event_1_state_0, handle_event_1_state_1, handle_event_2_state_1, handle_event_3_state_1}
    };
  
    int event = 0;
    int state = 1;

    while (1)
    {
        state = table[event][state](23); // the 23 is arbitrary, could be any useful datum or even be void ...
        // event = wait_for_next_event();
    }
}
You see the "state machine" is basically a loop, any kind of event that can occur is obtained as an int (from some other call) and used, along with the current state to a) call a handler and b) set the new state.

This way the system always reacts to an event in a way that is based on the system's current state and as the system is used that state itself changes. Coding this kind of behavior without an FSM can often be a big design flaw because once you try to represent this in other ways it get's messy with flags, if/then/ switch etc and can be a nightmare to debug as states or events are added to a growing design.

Calculators and lexical analyzers can be designed this way, most of the "programming" is then just a matter of correctly initializing the state transition table, and enhancing functionality is often just a matter of adding a new state or event, adding the handler and you're done - the existing functionality is very rarely impacted as changes and enhancements get made over time -> quality software, always something we want!

Writing this without having pointers to functions is much messier and more fragile.

(Note how the array elements can just be function names, the & isn't needed on each entry - this may be an implementation detail for the C compiler, not sure if it's C standard, I wrote that in Visual Studio).
 
Last edited:

xox

Joined Sep 8, 2017
936
Function pointers are very handy, a particularly good use for then is in finite state machines. In this design we have a 2D lookup table and the table stores function pointers.

A outer loop receives some kind of event or signal or whatever and it uses that event ID along with the current "state" ID (just integers) to index into the table and invokes the function that is at those coordinates. The function often (depends on design) returns the new state.

May sound like overkill but if you have more than say five or six events and five or six states and non-trivial processing for each state transition it is a very neat design, the outer loop is pretty simple and each event handler is a well defined function with a common signature and does a simple job.

I've done this several times for compiler and so on on, often debugging becomes little more than verifying that the 2D table is correctly initialized and that each function does return the correct next state, very complex behaviors can be implemented with very high reliability and very easy to read code.

Also as others will no doubt say function pointers are the bedrock of "callbacks" where we call some function and hand it the address of some other function that will get called when some thing happens, UART's for example use this.
The designers of C deserve a crown in heaven for including function pointers. Had they left them out of the language things like higher level languages wouldn't have been nearly so practicle to implement.

I've also used similar approaches to what you've described, and yes, much more efficient (and usually still quite readable as you say). Way back when I wrote a MiniBasic clone in C++ that used function pointers to map instuctions directly to their handlers. It too ran like the wind, even on large and complex datasets. Real time simulations.

And more recently in this toy project I put together just a few weeks ago I used the JS equivalent to convert each character of input to an index into a lookup table of handlers. That's constant time lookup so even though it's being executed on a very unoptimal interpreted engine, it still runs blazingly fast as a parser scanner/tokenizer. So just an overall useful paradigm really.
 

bug13

Joined Feb 13, 2012
2,002
Hello,
I'm struggling to understand function pointer, Please see below the attempt I've made so far :

Code:
#include <stdio.h>
int *add(int x, int y);
int main()
{
   int a = 5;
   int b = 4;
   return 0;
}

int *add(int x, int y)
{
    return x + y;
}
What is use of function pointer ?
What are you trying to do with your code? There is no function pointer in there as far as I can tell.
 

bug13

Joined Feb 13, 2012
2,002
Here's some useless code that show you what I mean by a table driven FSM (many FSM implementations are switch statements or even nested switch statements - very bad idea but for the most trivial cases).

Code:
#include<stdio.h>
#include<stdlib.h>

typedef int (*Handler_ptr)(int);

int handle_event_0_state_0(int X)
{
    // do stuff
    return 1;
}

int handle_event_1_state_0(int X)
{
    // do stuff
    return 2;
}

int handle_event_2_state_0(int X)
{
    // do stuff
    return 3;
}

int handle_event_3_state_0(int X)
{
    // do stuff
    return 0;
}

int handle_event_0_state_1(int X)
{
    // do stuff
    return 1;
}

int handle_event_1_state_1(int X)
{
    // do stuff
    return 2;
}

int handle_event_2_state_1(int X)
{
    // do stuff
    return 3;
}

int handle_event_3_state_1(int X)
{
    // do stuff
    return 0;
}

int  main() {

    Handler_ptr table[4][4] =
    {
        {handle_event_0_state_0, handle_event_1_state_0, handle_event_2_state_0, handle_event_3_state_0},
        {handle_event_1_state_0, handle_event_1_state_1, handle_event_2_state_1, handle_event_3_state_1}
    };
 
    int event = 0;
    int state = 1;

    while (1)
    {
        state = table[event][state](23); // the 23 is arbitrary, could be any useful datum or even be void ...
        // event = wait_for_next_event();
    }
}
That's a great idea, I think this will be another useful trick I learn off you.
 
Top