Cerike
Cerike

Reputation: 364

Function Definition/Declaration Using Function Pointer `typedef` in C

UPDATE:

This was just something stupid. My PC crashed a few minutes after this, and after restart it throws the same error as to everyone else... Even when I go back to the original version using GIT. I guess something got messed up in the PCs RAM? XD

In C, can a function pointer type be used to declare and define a function?

I did this by mistake, but it worked as expected without throwing any warnings:

init.h:

typedef bool (*InitFunc)(void);

init.c:

#include <init.h>
#include <moduleX.h>

InitFunc initFuncs[N];

bool init(void)
{    
    ...

    initFuncs[n] = &moduleX_Init;

    ...
}

bool initTask(void* Args)
{

    initFuncs[n]();

}

moduleX.h:

#include <init.h>

InitFunc moduleX_Init(void);

moduleX.c:

#include <moduleX.h>

InitFunc moduleX_Init(void)
{
    
    ...
        
    return true;
}

As you can see, I defined the function moduleX_Init using the typedef of the function pointer. It compiled using GCC (arm-none-eabi-gcc) without even an warning and worked as expected.

I only did this by mistake, but when I noticed it, I was wondering if this is actually a compliant way to declare a function or it just happens to work with GCC.

EDIT:

If I do the declaration like this InitFunc moduleX_Init;, then I get the following error:

incompatible types when assigning to type InitFunc {aka _Bool (*)(void)}' from type '_Bool'

So it seams, that when used in variable declarations, the function pointer types work as if they were a typedef of the return type. Is this standard behavior, or just the particularity of GCC?

Upvotes: 0

Views: 1067

Answers (3)

arfneto
arfneto

Reputation: 1765

In C, can a function pointer type be used to declare and define a function?

No. A function pointer is just a pointer. You can use it to call the function is points to, and for any case a pointer can be used

I did this by mistake, but it worked as expected without throwing any warnings

Well, as for the "any warnings" part compilers here disagree with you. For this line:

    typedef bool (*InitFunc)(void);

clang 10 compiler says

dsp$ clang -c min.c
min.c:2:16: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
typedef bool (*InitFunc)(void);
               ^
min.c:2:9: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
typedef bool (*InitFunc)(void);
~~~~~~~ ^
min.c:2:14: error: function cannot return function type 'int (void)'
typedef bool (*InitFunc)(void);
             ^
2 warnings and 1 error generated.

And gcc 9.3 says

dsp$ gcc -c min.c
min.c:2:15: error: expected declaration specifiers or ‘...’ before ‘*’ token
    2 | typedef bool (*InitFunc)(void);
      |               ^

As for the part "it worked as expected" what your expectations were?

Another similar typedef

typedef int(*Pfri)(int);

This is fairly common stuff and declares the name Pfri as a pointer to a function that returns an int and takes one int as argument, and this time the compilers will be happy with it.

C Example using this

#define N 10
#include    <stdio.h>

typedef int(*Pfri)(int);

int plus3(int i) { return i*3; };
int plus4(int i) { return i*4; };

int main(void)
{
    Pfri    initFunc[N];
    printf("fills array of function pointers\n");
    for( int i = 0; i<N; i+=2 )
        initFunc[i] = plus4, initFunc[1+i] = plus3;
    printf("\
For odd indexes, function is \"int plus3(int i) { return i*3; };\"\n\
For even  indexes, function is \"int plus4(int i) { return i*4; };\"\n\
Array has %d functions\n", N);
    for( int i=0; i<N; i+=1 )
        printf("f(%d)=%d\n", i,initFunc[i](i) );
    return 0;
}

This program:

  • takes the above mentioned typedef and declares an array of them.
  • declares 2 functions compatible with this typedefed name
  • fills the array with pointers to the functions
  • calls each one and displays the results

Output

fills array of function pointers
For odd indexes, function is "int plus3(int i) { return i*3; };"
For even  indexes, function is "int plus4(int i) { return i*4; };"
Array has 10 functions
f(0)=0
f(1)=3
f(2)=8
f(3)=9
f(4)=16
f(5)=15
f(6)=24
f(7)=21
f(8)=32
f(9)=27

Upvotes: 0

user9706
user9706

Reputation:

No, you cannot use a function pointer typedef to declare or define a function. You can use use to use function pointer typedefs to specify the type of the return value and arguments.

You are declaring moduleX_Init to return a function pointer. Is that what you wanted? @SergeyA already gave you the warning for the assignment and here is the warning you get for moduleX_Init (gcc 8.3.0-6 without any arguments other the input file):

1.c: In function ‘moduleX_Init’:
1.c:6:9: warning: returning ‘int’ from a function with return type ‘InitFunc’ {aka ‘_Bool (*)(void)’} makes pointer from integer without a cast [-Wint-conversion]                                                                            
  return true;
         ^~~~

Upvotes: 1

SergeyA
SergeyA

Reputation: 62563

Your code is malformed, and there is no way it could have been compiled without warnings. Here is the one I am getting with your code:

<source>: In function 'init': <source>:11:18: warning: assignment to 'InitFunc' {aka '_Bool (*)(void)'} from incompatible pointer type '_Bool (* (*)(void))(void)' [-Wincompatible-pointer-types]

Your declaration

typedef bool (*InitFunc)(void);

InitFunc moduleX_Init(void);

declares a function which returns a pointer to function. By itself, there is nothing wrong with it, but when you try to use it like this:

initFuncs[n] = &moduleX_Init;

You are assigning function pointers with incompatible signatures, as initFuncs[n] has a type bool (*)(void).

Upvotes: 0

Related Questions