Thread: function pointer and void*

  1. #1
    Registered User Sargnagel's Avatar
    Join Date
    Aug 2002
    Posts
    166

    Angry function pointer and void*

    Code:
    /* function pointers to comparison functions	*/
    typedef int (*DoubleCompFunc)(double, double);
    typedef int (*IntCompFunc)(int, int);
    
    /* comparison functions	*/
    static int cmp_lt(const double a, const double b)	{	return a < b;	}
    static int cmp_le(const double a, const double b)	{   return a <= b;	}
    static int cmp_eq(const double a, const double b)	{	return a == b;	}
    static int cmp_ge(const double a, const double b)	{   return a >= b;	}
    static int cmp_gt(const double a, const double b)	{   return a > b;	}
    
    static int icmp_lt(const int a, const int b)		{	return a < b;	}
    static int icmp_le(const int a, const int b) 		{   return a <= b;	}
    static int icmp_eq(const int a, const int b) 		{   return a == b;	}
    static int icmp_ge(const int a, const int b) 		{   return a >= b;	}
    static int icmp_gt(const int a, const int b) 		{   return a > b;	}
    /************************/
    /**	depending on the relational operator stored in relop[] the function
     *	pointer *ptr is set to point to the appropriate comparison function
     */
    static int setDoubleCompFuncPtr(char relop[], DoubleCompFunc *ptr)
    {
    	if(strcmp(relop, "lt") == 0)		*ptr = cmp_lt;
    	else if(strcmp(relop, "le") == 0)	*ptr = cmp_le;
    	else if(strcmp(relop, "eq") == 0)	*ptr = cmp_eq;
    	else if(strcmp(relop, "ge") == 0)	*ptr = cmp_ge;
    	else if(strcmp(relop, "gt") == 0)	*ptr = cmp_gt;
    	else
    		//error handling
    	return 1;
    }
    
    static int setIntCompFuncPtr(char relop[], IntCompFunc *ptr)
    {
    	if(strcmp(relop, "lt") == 0)		*ptr = icmp_lt;
    	else if(strcmp(relop, "le") == 0)	*ptr = icmp_le;
    	else if(strcmp(relop, "eq") == 0)	*ptr = icmp_eq;
    	else if(strcmp(relop, "ge") == 0)	*ptr = icmp_ge;
    	else if(strcmp(relop, "gt") == 0)	*ptr = icmp_gt;
    	else
    		//error handling
    	return 1;
    }
    How can I write a more generic function "setCompFuncPtr" instead
    of using the two functions above which contain almost identical code?
    ... some void pointer action, I guess ...

    I've tried the following:
    Code:
    int main(...)
    {
    	...
    	DoubleCompFunc compFunc;
    	DoubleCompFunc dblfptr[] = {cmp_lt, cmp_le, cmp_eq, cmp_ge, cmp_gt};
    	IntCompFunc intfptr[] = {icmp_lt, icmp_le, icmp_eq, icmp_ge, icmp_gt};
    	...
    	if( (setCompFuncPtr("gt", compFunc, dblfptr)) == 0)
       		return -1;
    	...
    	return 0;
    }
    
    static int setCompFuncPtr(char relop[], void *ptr, void *fptr)
    {
    	if(strcmp(relop, "lt") == 0)		*ptr = fptr[0];
    	else if(strcmp(relop, "le") == 0)	*ptr = fptr[1];
    	else if(strcmp(relop, "eq") == 0)	*ptr = fptr[2];
    	else if(strcmp(relop, "ge") == 0)	*ptr = fptr[3];
    	else if(strcmp(relop, "gt") == 0)	*ptr = fptr[4];
    	else
    		//error handling
    	return 1;
    }
    But that produces lots of junk or a segmentation fault. And the compiler
    throughs some warnings about dereferencing void pointers in the function
    setCompFuncPtr().
    What have I missed? I thought function pointers and void pointers had
    both the size of 4 bytes? So, where is the problem?
    [edit]
    Damn! Reading the FAQ before posting is truly helpful! "You may not dereference a void*"
    So, I guess, I will have to go with a simple if-else and typecast the void* appropriately ...
    [/edit]

    Thank you for your help!

    Compiler: gcc 3.2 (cygwin)
    OS: W2k
    CPU: Intel x86, 32bit
    Last edited by Sargnagel; 08-28-2003 at 12:37 PM.

  2. #2
    Comment your source code! Lynux-Penguin's Avatar
    Join Date
    Apr 2002
    Posts
    533
    Why are you typedefing them?

    the first thing I notice, and I really don't think typedef can be used that way, but im not sure.

    -LC
    Asking the right question is sometimes more important than knowing the answer.
    Please read the FAQ
    C Reference Card (A MUST!)
    Pointers and Memory
    The Essentials
    CString lib

  3. #3
    Registered User Sargnagel's Avatar
    Join Date
    Aug 2002
    Posts
    166
    typedef makes life easier

    I am sure that nothing is wrong with my typedef of function pointers.

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Would something like this be of use?
    Code:
    static DoubleCompFunc setDoubleCompFuncPtr(char relop[])
    {
       static const struct sDoubleCompFuncPtr
       {
          const char     *key;
          DoubleCompFunc  function;
       } DoubleFunc[] =
       {
          {"lt",cmp_lt},
          {"le",cmp_le},
          {"eq",cmp_eq},
          {"ge",cmp_ge},
          {"gt",cmp_gt},
       };
       size_t i;
       for ( i = 0; i < sizeof(DoubleFunc)/sizeof(*DoubleFunc); ++i )
       {
          if ( strcmp(relop, DoubleFunc[i].key) == 0 )
          {
             return DoubleFunc[i].function;
          }
       }
       return NULL; /* [edit]Added link[/edit] */
    }
    
    int main(void)
    {
       double a = 3.14, b = 1.23;
       DoubleCompFunc func = setDoubleCompFuncPtr("lt");
       if(func)
       {
          printf("%f,%f,%d\n", a, b, func(a,b));
       }
       func = setDoubleCompFuncPtr("gt");
       if(func)
       {
          printf("%f,%f,%d\n", a, b, func(a,b));
       }
       return 0;
    }
    
    /* my output
    3.140000,1.230000,0
    3.140000,1.230000,1
    */
    And by the way, you shouldn't test floats for equality like that.
    http://www.eskimo.com/~scs/C-faq/q14.5.html
    Last edited by Dave_Sinkula; 08-28-2003 at 01:15 PM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #5
    Registered User Sargnagel's Avatar
    Join Date
    Aug 2002
    Posts
    166
    Dave, that's a neat implementation. I think it's easier to understand than my version.
    Thanks alot! I will implement your solution.

    @double comp:
    Hmmm ... I didn't spend much time thinking about it, but there is truly a problem. Now, I just have to choose an appropriate epsilon.
    Thanks again.

  6. #6
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    >I thought function pointers and void pointers had both the size of 4 bytes?

    Oops, I almost forgot -- I believe that pointers to void can point to any object; but no such guarantee is made for function pointers. That is, a void pointer might not fully contain a function pointer.
    More info.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  7. #7
    Registered User Sargnagel's Avatar
    Join Date
    Aug 2002
    Posts
    166
    Originally posted by Dave_Sinkula
    Oops, I almost forgot -- I believe that pointers to void can point to any object; but no such guarantee is made for function pointers. That is, a void pointer might not fully contain a function pointer.
    That explains the segmentation fault. So, a function pointer is a different beast?
    Is the true implemenation of function pointers quite different from normal pointers?

    @return NULL and function pointers:
    Hmmm!? I think I will pass another variable to the function and assign the function pointer that way. The return type of the function will be int again and that will indicate if an error has occured (return 0).
    Just to make sure nothing undefined happens when compiling the source code with other compilers.
    Thanks again!
    Last edited by Sargnagel; 08-28-2003 at 04:29 PM.

  8. #8
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >So, a function pointer is a different beast?
    >Is the true implemenation of function pointers quite different from normal pointers?
    On some machines, function addresses can be larger than data pointers, so using a void pointer to hold a function address is not portable. However, function pointers are interchangeable as long as you change them back before calling them. So you can use a "generic" function pointer like so:
    Code:
    int (*)()
    
    or
    
    void (*)()
    My best code is written with the delete key.

  9. #9
    Registered User Sargnagel's Avatar
    Join Date
    Aug 2002
    Posts
    166
    Originally posted by Prelude

    On some machines, function addresses can be larger than data pointers, so using a void pointer to hold a function address is not portable.
    Aha! That makes sense to me.
    Originally posted by Prelude
    However, function pointers are interchangeable as long as you change them back before calling them. So you can use a "generic" function pointer
    That's good news. I thought about it yesterday, but didn't find the time to ask.
    Thank you very much for your help, Prelude.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sorting number
    By Leslie in forum C Programming
    Replies: 8
    Last Post: 05-20-2009, 04:23 AM
  2. <Gulp>
    By kryptkat in forum Windows Programming
    Replies: 7
    Last Post: 01-14-2006, 01:03 PM
  3. Function Pointer help
    By Skydt in forum C Programming
    Replies: 5
    Last Post: 12-02-2005, 09:13 AM
  4. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM