Find the answer to your Linux question:
Page 1 of 2 1 2 LastLast
Results 1 to 10 of 17
Like Tree1Likes
Hello; I'm having a problem figuring out the right syntax for calling a pointer to a function with just a single pointer to function from inside a holder struct. I'm ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Oct 2013
    Posts
    47

    Single pointer to function - Syntax in GCC


    Hello;

    I'm having a problem figuring out the right syntax for calling a pointer to a function with just a single pointer to function from inside a holder struct. I'm using GCC to compile.

    This example works except for single - the compound struct with a single malloc-ed pointer to function. The error I get from GCC when compiling is

    test.c:72:71: error: called object ‘single->struct_array’ is not a function
    Here is the code in case attachment doesn't work...

    Code:
    #include <stdlib.h>
    #include <stdio.h>  
    
    
    // generic pointer to function
    typedef float(*pt2Func)(float, float);
    // generic compound structure
    typedef struct 
    {
    	int 		y;
    	double 		x;
    	pt2Func * struct_array;
    }compound_struct;
    
    /*
     * This test file examines the syntax and operation of function pointers
     * so that understanding is given to employment.
     */ 
     
    // generic functions with identical variables 
    float Plus     (float a, float b) { return a+b; }
    float Minus    (float a, float b) { return a-b; }
    float Multiply (float a, float b) { return a*b; }
    float Divide   (float a, float b) { return a/b; }
    float Nothing  (float a, float b) { return 0; }
    
    // assigning function pointers in file out of scope
    int AssignFunctions( compound_struct * out )
    {
    	if (out != 0)
    	{
    		out->struct_array[4]  = Plus;
    		out->struct_array[5]  = Minus;
    		out->struct_array[6]  = Multiply;			
    		out->struct_array[7]  = Divide;
    		
    	}
    	return 0;
    }
    
    int main ( int argc, char *argv[] )
    {
    	// in is an example structure that contains an array of function pointers.
    	compound_struct * in;
    	float a = 5;
    	float b = 6;
    	// allocated in main variable array
    	pt2Func * array;
    	compound_struct  * single;
    
    	
    	// a simple array of pointer to functions
    	array = malloc ( sizeof( pt2Func * ) * 10);
    	array[0] = Plus;
    	array[1] = Minus;
    	array[2] = Multiply;
    	array[3] = Divide;
    	//
    	int i = 0;
    	for (i = 0 ; i < 4; i++)
    	{
    		printf("dynamic allocated array answer %f  \n",array[i](a,b));
    	}
    	
    	//! struct with a single function
    	single = malloc( sizeof ( compound_struct) );		
    	single->struct_array = malloc ( sizeof( pt2Func * ) * 1);
    	single->x = 10.01;
    	single->y = 50;
    	// now aim fcn pointer to the addition
    	single->struct_array[0] = Plus;
    	
    	printf("single answer for 10.01 + 50 =  %f  \n", single->struct_array(single->x, single->y)  );
    		
    	
    	//! in is the array version inside a struct
    	in = malloc  (sizeof ( compound_struct));
    	in->x = 1;
    	in->y = 27.03445;
    	in->struct_array = malloc ( sizeof( pt2Func * ) * 10);
    	for (i = 0 ; i < 10; i++)
    	{
    		in->struct_array[i] = Nothing;
    	}
    	
    	in->struct_array[0] = Plus;
    	in->struct_array[1] = Minus;
    	in->struct_array[2] = Multiply;
    	in->struct_array[3] = Divide;
    	
    	AssignFunctions( in );
    	
    	for (i = 0 ; i < 10; i++)
    	{
    		printf("dynamically allocated in compound struct array answer %f  \n",in->struct_array[i](a,in->y));
    	}	
    	
    	AssignFunctions2( in );
    	
    	for (i = 0 ; i < 10; i++)
    	{
    		printf("out of file scope dynamically allocated in compound struct array answer %f  \n",in->struct_array[i](a,in->y));
    	}	
    	// calling pointer to functions
    	printf("Function call 0  =   %f\n",in->struct_array[0](in->x,in->y));
    	printf("Function call 1  =   %f\n",in->struct_array[1](in->x,in->y));	
    	printf("Function call 2  =   %f\n",in->struct_array[2](in->x,in->y));		
    	printf("Function call 3 =   %f\n",in->struct_array[3](in->x,in->y));		
    	
    	
    	free( in);
    	free(array);	
    	
    	return 0;
    }

  2. #2
    Linux Guru
    Join Date
    Dec 2013
    Location
    Victoria, B.C. Canada
    Posts
    1,655
    There's a number of things wrong conceptually but to get it to compile using:
    Code:
    gcc -std=c11 -Wall -pedantic funcptr.c -o funcptr
    I commented the undefined function AssignFunction2 and called:
    Code:
    single->struct_array(single->x, single->y)
    like so
    Code:
    single->struct_array[0](single->x, single->y)

  3. #3
    Just Joined!
    Join Date
    Oct 2013
    Posts
    47
    Conceptually, not sure what's wrong with simple demo code for educational purposes? It's simple to enlghten implementation.

    I did have [0] before and got a seg fault, perhaps I was mistake to change that, thanks for the syntax change.

    Why did you employ -std=c11 -Wall -pedantic cflags and what change would these make?

    Thanks for responding.

    Dave

  4. $spacer_open
    $spacer_close
  5. #4
    Linux Guru
    Join Date
    Dec 2013
    Location
    Victoria, B.C. Canada
    Posts
    1,655
    Well, conceptually I meant from a programming point of view not one of purpose.

    gcc defaults warn if you use comments like // which weren't legal C in early versions of the specification. In earlier versions of C declarations had to be at the beginning of a block. -std=c11 tells the compiler to use the latest specification so those things are legal. -Wall tells the compiler to turn all warnings on and -pedantic tells the compiler to issue all warning required by the ISO spec and reject forbidden extensions. Using these options can help find problem areas in code.

    When determining the size of pointer required to build an array of function pointers you actually want the size of the function pointer but in your code you are using the size of a pointer to a function pointer.

    Here's a short example illustrating.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int x2 (int num) {
            return num * 2;
    }
    
    int x3 (int num) {
            return num * 3;
    }
    
    typedef int (*MPTR) (int);
    
    int main () {
            MPTR* ptr_arr;
    
            ptr_arr = (MPTR*) malloc (sizeof(MPTR) * 2);
            if (ptr_arr == NULL) {
                    printf ("Memory issue");
                    exit (EXIT_FAILURE);
            }       
    
            ptr_arr[0] = x2;
            ptr_arr[1] = x3;
    
            printf ("%d\n", ptr_arr[0](2));
            printf ("%d\n", ptr_arr[1](2));
    
            free (ptr_arr);
    
            return EXIT_SUCCESS;
    }

  6. #5
    Just Joined!
    Join Date
    Oct 2013
    Posts
    47
    Understood; well conceptually, a pointer is an address with a type cast associated with it. I could malloc * void and it would still work with the code and a type cast to type. SInce a pointer address is always the same size and no implementation has a smaller address by default (exceptions are possible not talking about unique data types or unions etc. ). I wrote it with a one to one type for legibility/ clarity. Your implementation is type specific. Notice I don't need a typecast?

  7. #6
    Linux Guru
    Join Date
    Dec 2013
    Location
    Victoria, B.C. Canada
    Posts
    1,655
    There's no guarantee that two pointer are going to be the same size. A pointer to a function pointer is not the same thing as a pointer to a function. The only thing you're guaranteed is that a void* is large enough to hold any other pointer type. On many platforms it may make no difference. It's still wrong.

  8. #7
    Just Joined!
    Join Date
    Oct 2013
    Posts
    47
    c - What is guaranteed about the size of a function pointer? - Stack Overflow

    From C99 spec, section 6.2.5, paragraph 27:

    A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.


    "


    No, no, no.

    C doesn't favour Harvard architectures with different code and data pointer sizes, because ideally when programming for such an architecture you want to store data in program memory (string literals and the like), and to do that you'd need object pointers into the code space. But it doesn't forbid them, so as far as the standard is concerned function pointers can refer to an address space which has a different size from the data address space.

    However, any function pointer can be cast to another function pointer type[*] and back without trashing the value, in the same way that any object pointer can be cast to void* and back. So it would be rather surprising for function pointers to vary in size according to their signature. There's no obvious "use" for the extra space, if you have to be able to somehow store the same value in less space and then retrieve it when cast back."

  9. #8
    Linux Guru
    Join Date
    Dec 2013
    Location
    Victoria, B.C. Canada
    Posts
    1,655
    What is your point. Your program indicates you don't understand the use of pointers and their relationship to arrays. If you want to keep using pointers in a manner that makes no sense - knock yourself out.
    docbop likes this.

  10. #9
    Just Joined!
    Join Date
    Oct 2013
    Posts
    47
    Thank you for your comments, although I think the words from another programmer were self-explanatory, there is a reason why you can assume the pointer size is same. I'm not saying you should always assume. But C specs are clear...

  11. #10
    Just Joined!
    Join Date
    Oct 2013
    Posts
    47
    Just so you are clear what I was saying implicitly: a pointer - any kind of pointer - is an address - that's it. It's an address with a context - a type of data that will be located at that address. The context tells the system what size of object is on the other side of that pointer address. But the address itself is still the size of a system address, normally fits into one register because that is where a pointer is accessed in a fetch push pull reference dereference or whatever your instruction codes are. So unless you are specifically using a Harvard model computer with different address spaces or you are using some special type that has a smaller or larger size defined custom for your application, you can reasonably assume the address is the size or a regular address

Page 1 of 2 1 2 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •