Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Better Use of Function Pointers

kittu20

New Member
I can write the c program using the function pointer to call the function using the pointer instead of function name, but I don't understand the reason why use function pointer instead of using the function name.

If you really know the advantage of function pointers, could you help me understand how the function pointer gives the advantage over using function names?
 
Just google "c function pointer examples"

An example here - https://www.guru99.com/c-function-pointers.html

Think of multiple f()'s, each which process a common dataset differently
because of some property in the dataset. One could of course write one
f(), and detect the property in the f() and execute a CASE structure. But
if each CASE is a whole unique process under itself writing separate f()'s
makes more sense....


Regards, Dana.
 
Just google "c function pointer examples"
Regards, Dana.
As mentioned earlier, I can write code like the one below, but I still don't understand why we should only use function pointers. It's like having two tools to solve a problem; you should have a good reason to use a specific tool. Surely, you would choose the tool that is more efficient in solving your problems. So how do you know that function pointer is more suitable to solve your problem

C:
#include <stdio.h>

void foo()
{
    printf(" Welcome ");
}

int main()
{
    
       void (*fp)() = &foo;
    // foo();
    fp();
  
    return 0;
}
 
You shouldn't only use f() pointers. Is this a constraint from a school work problem ?

As stated they can be useful in some situations, the programmer decides what situation
that should be. I see them as elegant ways of handling complex data interpretation from
a common dataset, eg. program readability, maintenance.....

And by not creating complex CASE statements as alternative, hence easier to debug, read,
wade thru the code......

Lastly you get "computed" code processing, the call dependent on values and / or properties.


Regards, Dana.
 
You shouldn't only use f() pointers. Is this a constraint from a school work problem ?
It's not homework assignment.

As you mentioned "complex CASE statements" we can develop a state machine using the switch case statement.

However, I'm curious about situations in your projects when you choose to use function pointers.

Can you elaborate on that so we will be able to discuss more ?
 
Last edited:
A couple of examples-
If you have a multi-function state machine, where each state does different processing, rather than use a switch statement and multiple comparisons for all the states to call their respective functions, you could create an array of function pointers and call the correct function directly by it's index number.

Another is for callback functions - eg. you have such as an interrupt driver timer as a library function but want to be able to define the function for each usage of it, or at runtime.

You can call its initialisation routine and as well as the interval or delay, pass a pointer to the function you want it to call at whatever intervals, or when a set time expires.
 
A couple of examples-
If you have a multi-function state machine, where each state does different processing, rather than use a switch statement and multiple comparisons for all the states to call their respective functions, you could create an array of function pointers and call the correct function directly by it's index number.
I've written code for a two-way traffic light control system as a hobby project. I developed the state machine using the switch case statement. Do you think in this situation, using function pointers would be helpful?

C:
#include <xc.h>
#include <stdio.h>

#define RED_PIN_1    LATB0
#define GREEN_PIN_1  LATB1
#define YELLOW_PIN_1 LATB2

#define RED_PIN_2    LATB3
#define GREEN_PIN_2  LATB4
#define YELLOW_PIN_2 LATB5

#define PEDESTRIAN_CROSS_BLUE LATB6
#define PEDESTRIAN_DONT_CROSS_RED LATB7

enum LightState {
    RED_STATE,
    YELLOW_STATE,
    GREEN_STATE
};


enum LightState currentLightState = RED_STATE;


volatile unsigned int elapsedTime = 0;

void initializeHardware() {
    TRISB0 = 0;
    TRISB1 = 0;
    TRISB2 = 0;

    TRISB3 = 0;
    TRISB4 = 0;
    TRISB5 = 0;
    TRISB6 = 0;
    TRISB7 = 0;

    LATB = 0x00;

    RED_PIN_1 = 1;
    YELLOW_PIN_1 = 0;
    GREEN_PIN_1 = 0;

    RED_PIN_2 = 1;
    YELLOW_PIN_2 = 0;
    GREEN_PIN_2 = 0;
 
    PEDESTRIAN_CROSS_BLUE = 1;
    PEDESTRIAN_DONT_CROSS_RED = 0;

    ANCON0 = 0x00;
    ANCON1 = 0x00;

    INTCON = 0;

    INTCONbits.GIE = 1;
    INTCONbits.PEIE = 1;
}

void initializeTimer2(void) {
    T2CONbits.T2OUTPS = 0b0000;
    T2CONbits.TMR2ON = 1;
    T2CONbits.T2CKPS = 0b10;
    PR2 = 124;

    PIE1bits.TMR2IE = 1;
}

void main(void) {
    initializeHardware();
    initializeTimer2();

    while (1) {
        unsigned int tempElapsedTime = elapsedTime;

        // Temporarily disable global interrupts
        INTCONbits.GIE = 0;

        // Re-enable global interrupts
        INTCONbits.GIE = 1;

        // Update traffic light states and pedestrian signals
        switch (currentLightState) {
            case RED_STATE:
                if (tempElapsedTime >= 20000) {
                    currentLightState = GREEN_STATE;
                    INTCONbits.GIE = 0;
                    elapsedTime = 0;
                    INTCONbits.GIE = 1;
                    RED_PIN_1 = 0;
                    GREEN_PIN_1 = 1;
                    YELLOW_PIN_1 = 0;
                  

                    RED_PIN_2 = 0;
                    GREEN_PIN_2 = 1;
                    YELLOW_PIN_2 = 0;

                    PEDESTRIAN_CROSS_BLUE = 0;
                    PEDESTRIAN_DONT_CROSS_RED = 1;
                
                }
                break;
            case GREEN_STATE:
                if (tempElapsedTime >= 20000) {
                    currentLightState = YELLOW_STATE;
                    INTCONbits.GIE = 0;
                    elapsedTime = 0;
                    INTCONbits.GIE = 1;
                    RED_PIN_1 = 0;
                    YELLOW_PIN_1 = 1;
                    GREEN_PIN_1 = 0;

                    RED_PIN_2 = 0;
                    YELLOW_PIN_2 = 1;
                    GREEN_PIN_2 = 0;

                    PEDESTRIAN_CROSS_BLUE = 0;
                    PEDESTRIAN_DONT_CROSS_RED = 1;
                  
                }
                break;
            case YELLOW_STATE:
                if (tempElapsedTime >= 3000) {
                    currentLightState = RED_STATE;
                    INTCONbits.GIE = 0;
                    elapsedTime = 0;
                    INTCONbits.GIE = 1;
                    RED_PIN_1 = 1;
                    YELLOW_PIN_1 = 0;
                    GREEN_PIN_1 = 0;

                    RED_PIN_2 = 1;
                    YELLOW_PIN_2 = 0;
                    GREEN_PIN_2 = 0;

                    PEDESTRIAN_CROSS_BLUE = 1;
                    PEDESTRIAN_DONT_CROSS_RED = 0;
                }
                break;
        }
    }
}


void __interrupt() ISR(void) {
    PIR1bits.TMR2IF = 0;
    elapsedTime++;
}
 
CASE statement here quite appropriate, I dont see anything to gain by using f() pointer.

That being said would be instructive to write it both ways and see if compiler is more
efficient with f() pointer references versus standard CASE.

I had a problem where I was running out of code space in an application, so did a program
wide conversion to pointers for values. Compiler gave me back ~ 25% freed up code space.
So makes me wonder how compiler does with f() pointers......is there less stack thrashing
for example that would impact ISR servicing or general thruput......

That being said I confess to never having used a f() pointer, although I can think of a couple
of applications where I should have investigated their use in hindsight.

I am not an expert here in C or any of the other languages I have used, for your information.

As an aside here is another way of doing traffic light state machine (on ARM) :



This used a tiny fraction of this SOC's resources......


Regards, Dana.
 
Compilers report memory usage.

That particular processor was PSOC 1 SOC, 29466, tool used Cypress PSOC Designer 5.4. Code
space was 32K limited. 2010 timeframe.

That family largely replaced now with PSOC 4, PSOC 5LP, PSOC Creator is IDE, Compiler GNU.

PSOC 5LP family has this onchip, multiple copies in many cases :

1707588402863.png




Regards, Dana.
 
Compilers report memory usage.

That particular processor was PSOC 1 SOC, 29466, tool used Cypress PSOC Designer 5.4. Code
space was 32K limited. 2010 timeframe.

That family largely replaced now with PSOC 4, PSOC 5LP, PSOC Creator is IDE, Compiler GNU.
I realize we're shifting from the original topic, but I'm interested on understanding more about memory usage, as you mentioned. Generally, a memory layout is divided into four segments: text, data, stack, and heap. Text is used to store the program, while data is further divided into initialized and uninitialized sections. In the data segment, global and static variables are stored, local variables are stored in the stack, and dynamic memory is allocated in the heap.

Can you monitor memory for these four segments in your setup?
 
No, those tools were not that sophisticated. Nothing in stack and heap other than setting
those with a guess.


Regards, Dana.
 

Latest threads

New Articles From Microcontroller Tips

Back
Top