Thread: multi-argument function pointer and enum

  1. #1
    Registered User
    Join Date
    Jan 2016
    Posts
    76

    multi-argument function pointer and enum

    Hi,

    I have two main questions:

    1. How to design a function pointer that can deal with various types of functions ?

    For example, I have a function that receive 3 arguments. I tried to assign it to a function pointer which worked by assigning and one typecasting, but when calling the function pointer, I couldn't pass the 3 arguments as in the original function.

    This is my example:


    Code:
    void (*fun_ptr)(void *);
    
    
    void write_chars(uint8_t row, uint8_t col, char *str){    str_ptr = str;
        uint8_t i;
        i = strlen(str_ptr);
        printf("size of string is %d\n",i);
        printf("%s",str_ptr);
        fun_ptr = (void*)&write_chars;
    }
    
    
    int main(){
    
    
        fun_ptr((void*)1,(void*)1,(void*)"messaage1");
    
    
    
    
        return 0;
    }

    2. What is the difference between
    Code:
    typedef enum
    and just
    Code:
    enum
    in libraries ? And does it put any difference when using it in another library?

    Almost +%90 of libraries files I open are using typedef, but I don't know why.

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,189
    fun_ptr is a pointer that can point to a function with the given signature. The way you have it, not only does it have the wrong signature, but it doesn't even point to anything since you haven't assigned anything to it. You need to assign a function to it.
    Code:
    #include <stdio.h>
    #include <stdint.h>
     
    void write_chars(uint8_t row, uint8_t col, char *str) {
        printf("%d %d %s\n", (int)row, (int)col, str);
    }
     
    int main() {
        void (*fp)(uint8_t, uint8_t, char*);
        fp = write_chars;
        fp(1, 1, "message1");
        return 0;
    }
    typedefs are used to create aliases for types.
    Code:
    typedef int MYINT;
    // now you can say:
    MYINT i, j, k;
    enums and structs need the keyword enum or struct, respectively, in front of them when they are used:
    Code:
    // Suppose we have this enum and struct:
     
    enum AnEnum { Zero, One, Two, Three };
     
    struct AStruct {
        int a, b;
    };
     
    // Then we can define variables of these types like so:
    enum AnEnum e = Two;   // we need to say "enum" first
    struct AStruct s;      // we need to say "struct" first
    If you don't want to have to say "enum" or "struct" in front of these, you can use a typedef:
    Code:
    // Note that we can use the same name (or a different name) for the typedef
    typedef enum AnEnum AnEnum;         // using the same name
    typedef struct AStruct MyStruct;    // using a different name
     
    // Now we can just say
    AnEnum e = Two;
    MyStruct s;
    We live as it were by chance, and by chance we are governed. - Seneca

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,796
    > 1. How to design a function pointer that can deal with various types of functions ?
    In C, the empty parameter list means any parameters, which is the closest you're going to get.
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<stdint.h>
    
    void (*fun_ptr)();
    
    void write_chars(uint8_t row, uint8_t col, char *str){
        uint8_t i;
        i = strlen(str);
        printf("size of string is %d\n",i);
        printf("%s\n",str);
    }
    
    int main(){
        fun_ptr = (void(*)())write_chars;
        fun_ptr(1,1,"messaage1");
        return 0;
    }
    But there are a couple of important gotcha's to be mindful of.
    1. There is ZERO parameter checking. The compiler will compile fun_ptr(42.0,"bananas"); without a peep, and leave you to figure out the run-time chaos.
    2. All the parameters you pass will undergo default promotions. Your actual function needs to be compatible with this.
    Quote Originally Posted by c99
    If the expression that denotes the called function has a type that does not include a
    prototype, the integer promotions are performed on each argument, and arguments that
    have type float are promoted to double. These are called the default argument
    promotions. If the number of arguments does not agree with the number of parameters,
    the behavior is undefined. If the function is defined with a type that includes a prototype,
    and either the prototype ends with an ellipsis (, ...) or the types of the arguments after
    promotion are not compatible with the types of the parameters, the behavior is undefined.
    If the function is defined with a type that does not include a prototype, and the types of
    the arguments after promotion are not compatible with those of the parameters after
    promotion, the behavior is undefined, except for the following cases:
    — one promoted type is a signed integer type, the other promoted type is the
    corresponding unsigned integer type, and the value is representable in both types;
    — one type is pointer to void and the other is a pointer to a character type.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Jan 2016
    Posts
    76
    Quote Originally Posted by john.c View Post
    fun_ptr is a pointer that can point to a function with the given signature. The way you have it, not only does it have the wrong signature, but it doesn't even point to anything since you haven't assigned anything to it. You need to assign a function to it.
    Code:
        void (*fp)(uint8_t, uint8_t, char*);
        fp = write_chars;
        fp(1, 1, "message1");
    Isn't there a way to declare a function pointer with a form that can receive any type of function ?

    Because I have different types of functions; for example,

    Code:
    void fun1(uint8_t num, uint8_t a, uint8_t b);void fun2(uint8_t *arr);
    void fun3(uint8_t a, uint8_t b);
    uint8_t fun4(void);
    So some functions wiht different argument set, receive 2 or 3. Also whether it returns a value or not.

    Can't I just do one function pointer and use it ?




    typedefs are used to create aliases for types.

    enums and structs need the keyword enum or struct, respectively, in front of them when they are used:

    OK, what is the difference between this:


    Code:
    // structstypedef struct {
    
    
    }TASK_MANAGER;

    and this:

    Code:
    // structstypedef struct TASK_MANAGER{
    
    
    }TASK_MANAGER;
    ?


    This issues a warning:

    Code:
    // structstypedef struct TASK_MANAGER{
    
    
    };

  5. #5
    Registered User
    Join Date
    Dec 2017
    Posts
    1,189
    Isn't there a way to declare a function pointer with a form that can receive any type of function ?
    Look at Salem's post.

    As for your other questions, I assume you meant:
    Code:
    // 1
    typedef struct {
     
    } TASK_MANAGER;
     
    // 2
    typedef struct TASK_MANAGER {
     
    } TASK_MANAGER;
     
    // 3
    typedef struct TASK_MANAGER {
     
    };
    Example 1 declares a typedef called TASK_MANAGER for a struct that has no name. Anonymous structs are allowed.

    Example 2 defines a typedef called TASK_MANAGER for a struct that is also called TASK_MANAGER.

    Example 3 is an error since you are declaring a typedef but not giving it a name. It is not allowed to have an anonymous typedef since it wouldn't make sense.
    We live as it were by chance, and by chance we are governed. - Seneca

  6. #6
    Registered User
    Join Date
    Jan 2016
    Posts
    76
    Quote Originally Posted by john.c View Post
    Code:
    // 1
    typedef struct {
     
    } TASK_MANAGER;
     
    // 2
    typedef struct TASK_MANAGER {
     
    } TASK_MANAGER;
     
    // 3
    typedef struct TASK_MANAGER {
     
    };
    Example 1 declares a typedef called TASK_MANAGER for a struct that has no name. Anonymous structs are allowed.

    Example 2 defines a typedef called TASK_MANAGER for a struct that is also called TASK_MANAGER.

    Example 3 is an error since you are declaring a typedef but not giving it a name. It is not allowed to have an anonymous typedef since it wouldn't make sense.

    Thank you so much for clarifying this, didn't know this about stucts syntax, what about unions and enums, do they follow the same rules ?

  7. #7
    Registered User
    Join Date
    Dec 2017
    Posts
    1,189
    Yes.
    We live as it were by chance, and by chance we are governed. - Seneca

  8. #8
    Registered User
    Join Date
    Jan 2016
    Posts
    76
    I'm trying to do this:

    Code:
    void (*function_pointer)(void *);
    
    
    uint8_t fun1(uint8_t a, uint8_t b, uint8_t *str1){
        printf("%s",*str1);
        return a + b;
    }
    
    
    int main(){
    
    
        function_pointer = fun1;
        function_pointer(1,2,"hi");
    
    
    
    
        return 0;
    }
    and getting this error:

    error: too many arguments to function 'function_pointer'|
    Last edited by wolfrose; 01-14-2021 at 04:10 AM.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,796
    Read it again.
    multi-argument function pointer and enum

    The function pointer has to have ZERO parameters, no parameters, not void - just empty.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    Jan 2016
    Posts
    76
    OK, I tried that, and started with a function that returns 32-bit number.

    But got an error:

    Code:
    
    static unsigned int i;
    
    
    uint32_t micros(void){
        i++;
        return i;
    }
    
    void (*fun_ptr)();
    
    int main()
    {    
        uint32_t k;
        fun_ptr = &micros;
        k = (uint32_t*)fun_ptr();
        printf("%u\n",k);
    
    
        return 0;
    }

    Got this:

    |23|error: invalid use of void expression|

  11. #11
    Registered User
    Join Date
    Dec 2017
    Posts
    1,189
    multi-argument function pointer and enum-facepalm-jpg

    Don't make me resort to the double!
    (Read Salem's last post again! )
    We live as it were by chance, and by chance we are governed. - Seneca

  12. #12
    Registered User
    Join Date
    Jan 2021
    Posts
    30
    ye like for me right

  13. #13
    Registered User
    Join Date
    Jan 2016
    Posts
    76
    OK, sorry didn't notice the way of assigning the function pointer.

    I tested the code, it's working but I tried something else.

    What if the function is returning something ? how to design the function pointer in this case to adapt various types of functions; functions that return something and functions that returns void ?

    This is what I tried, I just changed the return value of the function write_chars.

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<stdint.h>
    
    
    void (*fun_ptr)();
    
    
    uint8_t write_chars(uint8_t row, uint8_t col, char *str){
        uint8_t i;
        i = strlen(str);
        printf("size of string is %d\n",i);
        printf("%s\n",str);
        return 0;
    }
    
    
    int main(){
        uint8_t i1;
        fun_ptr = (void(*)())write_chars;
        i1 = fun_ptr(1,1,"messaage1");
        return 0;
    }

  14. #14
    Registered User
    Join Date
    Jan 2016
    Posts
    76
    OK, I did little adjustments. I changed the function pointer to return a value, and this way I can use it with functions that return values and functions that returns void.


    Code:
    #include<stdio.h>#include<stdlib.h>
    #include<string.h>
    #include<stdint.h>
    
    uint8_t (*fun_ptr)();
    
    uint8_t read_chars(uint8_t address){
        uint8_t i;
        uint8_t *array_address;
        i = address;
        printf("address of array is 0x%.2x\n",i);
        return 0x0a;
    }
    
    uint8_t write_chars(uint8_t row, uint8_t col, char *str){
        uint8_t i;
        i = strlen(str);
        printf("size of string is %d\n",i);
        printf("%s\n",str);
        return 0;
    }
    
    int main(){
        uint8_t add_val;
    
        fun_ptr = (void(*)())read_chars;
        add_val = fun_ptr(1);
    
        fun_ptr = (void(*)())write_chars;
        fun_ptr(1,1,"messaage1");
    
    
        return 0;
    }

    Thank you guys I thought that this won't work of using a function pointer to point to anything ! That's really amazing.

    This should change my whole task manager project strategy completely.

    My current project is to do a task manger for Arduino which is a single core microcontroller.

    The goal is to design a multitasking system without giving the functions a slice of time to execute. It should run in round robin system.

    My project objectives:
    1. The design is just to control and manage the locking/unlocking of functions that require some time to execute.
    2. Rest of functions that don't require any delay, should run the normal sequence of program execution.
    3. There's only the init function of the LCD that requires multiple delays of 100ms and 40ms to finish, so this one I should keeps its lock one, and get back to it after the finish of each delay time.
    4. Managing everything else that requires timing; for example, temporary LCD messages that would appear on the screen for like 2-3 seconds and get back to a menu of anything else.
    Now with the availability of using function pointers, I now have two ways to design the task manager.

  15. #15
    Registered User
    Join Date
    Jan 2016
    Posts
    76
    Hello,

    I have another question regarding accessing struct in multiple source files. Should I post it here or open a new thread ?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. passing function pointer as argument
    By thagulf2017 in forum C Programming
    Replies: 2
    Last Post: 05-30-2017, 11:55 AM
  2. Array pointer as function argument?
    By mtn_student in forum C Programming
    Replies: 1
    Last Post: 09-27-2011, 03:25 PM
  3. Passing address or pointer as argument to function
    By Edelweiss in forum C Programming
    Replies: 7
    Last Post: 08-17-2011, 12:38 AM
  4. pointer as function argument
    By bertazoid in forum C Programming
    Replies: 1
    Last Post: 09-23-2010, 10:27 AM
  5. pointer and function argument question.
    By stevfletchcom in forum C Programming
    Replies: 5
    Last Post: 06-14-2010, 11:07 PM

Tags for this Thread