2

Can anyone explain these two lines of code in C:

void (*pfs)(void) = &fs;        
long int (*pfact)(int) = &fact; 
Islacine
  • 105
  • 2
  • 9

4 Answers4

3

To make these declarations more clear

void (*pfs)(void)=&fs;
long int (*pfact)(int)=&fact; 

you can introduce typedef names for function declarations as for example

typedef void FUNC1( void );
typedef long int FUNC2( int );

and then write

FUNC1 *pfs = &fs;
FUNC2 *pfact = &fact; 

So the original declarations declare pointers to functions of the specified types and initialize them with addresses of the given functions.

Here is a demonstrative program

#include <stdio.h>

typedef void FUNC1( void );
typedef long int FUNC2( int );

void fs( void )
{
    puts( "Hello Islacine" );
}

long int fact( int x )
{
    return x;
}

int main(void) 
{
    FUNC1 *pfs = &fs;
    FUNC2 *pfact = &fact;

    pfs();

    printf( "sizeof( long int ) = %zu\n", sizeof( pfact( 0 ) ) );

    return 0;
}

Its output might look like

Hello Islacine
sizeof( long int ) = 8

Take into account that instead of

    FUNC1 *pfs = &fs;
    FUNC2 *pfact = &fact;

or instead of

    void (*pfs)(void)=&fs;        
    long int (*pfact)(int)=&fact; 

you could even write

    FUNC1 *pfs = fs;
    FUNC2 *pfact = fact;

or

    void (*pfs)(void) = fs;        
    long int (*pfact)(int) = fact; 

because in expressions with rare exceptions a function designator is converted to pointer to function.

You could even write :)

    FUNC1 *pfs = *****fs;
    FUNC2 *pfact = *****fact;

or

    void (*pfs)(void) = *****fs;        
    long int (*pfact)(int) = *****fact; 

From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)

4 A function designator is an expression that has function type. Except when it is the operand of the sizeof operator65) or the unary & operator, a function designator with type ‘‘function returning type’’ is converted to an expression that has type ‘‘pointer to function returning type’’.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I found an OpenGL ES header file (in the official Khronos site) that does this, in fact. – Cpp plus 1 Nov 21 '17 at 20:49
  • 1
    That is an unusual way of using typedef for function pointers. More usual would be: `typedef void (*voidFnVoid_t)( void ) ;` And then `voidFnVoid_t pfs = fs`. In the typedef for `FUNC1` here, you cannot declare an object of type `FUNC1`, only `FUNC1*`, so it serves no purpose to have a "function type" as opposed to a "function-pointer type". – Clifford Nov 21 '17 at 21:34
  • @Clifford The post is not about usual or unusual in your opinion declarations. The post is about how to understand the declarations. – Vlad from Moscow Nov 21 '17 at 21:44
  • 1
    @VladfromMoscow : It was not a criticism, just a note for the reader to avoid any confusion. The OP did not understand the syntax as it was, and is likely to come across my suggested form and be confused by that as well. I would suggest he is less likely to come across your form - that is all. If I had a fundamentally better answer I'd have posted it. – Clifford Nov 21 '17 at 21:49
  • @Cppplus1 : Actually the OpenGL headers use typedef for function-pointers as I have suggested, not as shown in this answer (albeit hidden beneath layers of macros). – Clifford Nov 21 '17 at 22:07
  • @Clifford That's what I meant -- the typedefs. – Cpp plus 1 Nov 21 '17 at 22:09
  • @Cppplus1 : You have misunderstood my point; Vlad's typedefs are not the same as those in OpenGL. To be clear it is not the naming convention I am referring to, but `typedef void FUNC1( void )` vs `typedef void (*FUNC1)(void)` to use Vlad's naming style. – Clifford Nov 21 '17 at 22:13
  • 1
    @Clifford I didn't pay attention to that. I just read "typedefs" and wrote the comment. – Cpp plus 1 Nov 21 '17 at 22:16
  • @Clifford You can use a typedef to declare functions. – Vlad from Moscow Nov 21 '17 at 22:18
  • @VladfromMoscow : Indeed, my error. That too would perhaps be unusual however - I cannot see a use case for that. But as you say, perhaps that is beside the point. – Clifford Nov 21 '17 at 22:20
  • @Clifford For example in C++ this can be used to declare static member functions. – Vlad from Moscow Nov 21 '17 at 22:21
3

This syntax defines a function pointer. You can use them like this:

void a() {
    //do something
}

int main() {
    void (*functionPointer)();
    functionPointer = a;
    //or
    functionPointer = &a;

    //call the funcion pointer as you would a regular function
    functionPointer();
}

The main reasons to use function pointers are to make callback functions and "jump-tables " (This is in quotes because function pointer arrays are not really jump tables. Real jump tables can only be made in assembly language).

Cpp plus 1
  • 990
  • 8
  • 25
2

what does void(* ) (void) and int(* ) (int) mean in C?

They just mean pointer to function taking void argument and returning void.

void (*pfs)(void)=&fs; 

pfs is an pointer to function taking void as an argument and returning void. This has initialized with function of same signature type i.e fs here.

long int (*pfact)(int)=&fact; 

pfact is an pointer to function taking int as an argument and reutring long int. After the assignment pfact is pointing to function fact.

Additional Note:

There are tools to read complicated declaration. One of them is https://cdecl.org/. Also as others have pointed out better way to work with pointer to function is typdef them .

sameer chaudhari
  • 928
  • 7
  • 14
2

They are function pointers. In your example:

void (*pfs)(void)=&fs;

You are creating a variable named "pfs". This variable has the type of a function that takes in no arguments and returns nothing.

The following makes your examples much more clear.

return_type (*variable_name) (argument_list)

Now the right side of the = sign is pretty easy if you understand the first half.

All we do is assign the location of the function "fs" to our function pointer (variable) "pfs".

Here is a full example to demo the explanations above.

#include <stdio.h>
void my_print_method(int number) {
    printf("The number is: %d", number);
}
int main() {
    // Declare our function pointer variable
    void (*printer)(int);

    // Assign our function pointer 'printer' to the method 'my_print_method'
    printer = &my_print_method

    // We can also assign the method to our function pointer as such:
    printer = my_print_method

    // Use our function pointer as if it were a function
    (*printer)(55);

    // Keep in mind that that in C we can simply write the function call as such:
    printer(55);

}
Grayson Croom
  • 91
  • 1
  • 7