Array of structures of function pointers C - c

I'm trying to initialize an array of structures containing pointer on function :
typedef struct struct_actioncommand {
char *action;
void (*command)(my_type);
} type_actioncommand;
To initialize each pointer with its function name I'm using this method :
static const type_actioncommand g_cmd_tab[] = {
{"Action1", function1},
{"Action2", function2},
{"Action3", function3},
{NULL, NULL}
};
But it doesn't work.
When I try to compile with "gcc", I have the following message:
myfile.c:16:3: error: initialization from incompatible pointer type [-Werror]
{"Action1", function1},
^
myfile.c:16:3: error: (near initialization for g_cmd_tab[0].command) [-Werror]
myfile.c:17:3: error: initialization from incompatible pointer type [-Werror]
{"Action2", function2},
^
myfile.c:17:3: error: (near initialization for g_cmd_tab[1].command) [-Werror]
myfile.c:18:3: error: initialization from incompatible pointer type [-Werror]
{"Action3", function3},
^
myfile.c:18:3: error: (near initialization for g_cmd_tab[2].command) [-Werror]
cc1: all warnings being treated as errors
each function is defined according to this prototype :
void function1(my_type *var1);
I'm a little bit confuse now since I dont see how to fix my problem.
Any ideas?

In your struct, the command member:
void (*command)(my_type);
Has type "pointer to function which take a parameter of type my_type and returns void.
Your function:
void function1(my_type *var1);
Has type "function which takes a parameter of type my_type * and returns void.
The parameters of the function pointer don't match the parameters of the functions you assign to them. That makes the pointers incompatible.
To fix this, change the type of the function pointer to match the functions that are assigned to it:
void (*command)(my_type *);

Related

function definition without prototype

when function definition is below, and there is no function prototype.
int main(void)
{
func();
void (*pFunc)(void) = func;
}
void func(void)
{
}
main.c:3:2: warning: implicit declaration of function 'func' is invalid in C99 [-Wimplicit-function-declaration]
func();
^
main.c:4:9: error: incompatible function pointer types initializing 'void (*)(void)' with an expression of type 'int ()' [-Werror,-Wincompatible-function-pointer-types]
void (*pFunc)(void) = func;
^ ~~~~
main.c:4:9: warning: unused variable 'pFunc' [-Wunused-variable]
main.c:7:6: error: conflicting types for 'func'
void func(void)
^
main.c:3:2: note: previous implicit declaration is here
func();
^
2 warnings and 2 errors generated.
I can call a function without function prototpype(ignoring implicit function declaration), but why I can't get the adress of the function?
warning: implicit declaration of function 'func' is invalid in C99
What this actually says is: your code is not valid C. There is no telling what it will do and no guarantees.
func(); This invokes a non-standard gcc extension known as implicit function declarations/implicit int, which was once part of the C language a very long time ago. It means that it will take a guess of the types - always assuming that this is a function returning int and taking any parameter - same as if you would have typed int func();. Which is plain wrong and will not work.
error: incompatible function pointer types initializing 'void (*)(void)' with an expression of type 'int ()'
Since we got the function declaration completely wrong above, we get this compiler error. The function pointer is not compatible with the type declared.
error: conflicting types for 'func'
This error happens when we reach the function definition void func (void), which collides with the previous definition int func ();.
Solution:
Fix your compiler so that it gives errors when you write invalid C. See What compiler options are recommended for beginners learning C?
Move the function declaration outside and above main() and change it to void func (void);

typecast to (void *) when passing pointer to object

Consider the following snippet:
void my_func(int a, void *b);
...
struct my_struct s = { };
my_func(10, (void *)&s);
Is it necessary to typecast to (void *) when passing &s to the function?
A pointer to any type may be freely converted to or from a void * without a cast.
Section 6.3.2.3p1 of the C standard states:
A pointer to void may be converted to or from a pointer to any object
type. A pointer to any object type may be converted to a
pointer to void and back again; the result shall compare equal
to the original pointer.
The only time a cast is needed is if you pass a pointer to a variadic function like printf where an implicit conversion can't occur, since it won't know what the exact type being passed in is.
Note that, as with any pointer type, you can't "remove" a qualifier such as const when passing to a function without a cast. Sections 6.3.2.3p2 states:
For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal.
you do not have to with some exceptions as you may get the warning if the object which reference you pass to the function is volatile or const - generally has different attribute.
void ee(void *q)
{
pritntf("%p", q);
}
volatile int g;
const int f;
int main()
{
ee(&g);
ee(&f);
}
gives this warnings:
<source>: In function 'main':
<source>:17:8: warning: passing argument 1 of 'ee' discards 'volatile' qualifier from pointer target type [-Wdiscarded-qualifiers]
ee(&g);
^~
<source>:6:15: note: expected 'void *' but argument is of type 'volatile int *'
void ee(void *q)
~~~~~~^
<source>:18:8: warning: passing argument 1 of 'ee' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
ee(&f);
^~
<source>:6:15: note: expected 'void *' but argument is of type 'const int *'
void ee(void *q)
~~~~~~^
Compiler returned: 0
No, it is not required, it just makes the code clearer on what exactly is being passed to the function.

Function pointers in C: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]

Consider the following private function declarations:
static void ParseCore(SI_32 num_param,const t_config_param config_param[CONFIG_PARAM_BUFFER_SIZE]);
static void ParseGnss(SI_32 num_param,const t_config_param config_param[CONFIG_PARAM_BUFFER_SIZE]);
static void ParseEaf(SI_32 num_param,const t_config_param config_param[CONFIG_PARAM_BUFFER_SIZE]);
static void ParsePps(SI_32 num_param,const t_config_param config_param[CONFIG_PARAM_BUFFER_SIZE]);
static void ParseImu(SI_32 num_param,const t_config_param config_param[CONFIG_PARAM_BUFFER_SIZE]);
Inside the definition of another function within the same source file, I initialize the following pointer:
void (*ParseConfigGeneric)(SI_32, t_config_param*) = NULL;
All of the following assignments get the warning indicated in the post's title:
ParseConfigGeneric = &ParseCore;
ParseConfigGeneric = &ParseGnss;
ParseConfigGeneric = &ParseEaf;
ParseConfigGeneric = &ParsePps;
ParseConfigGeneric = &ParseImu;
And here the output from GCC:
../src/core/time_mgmt.c: In function ‘ParseConfigFile’:
../src/core/time_mgmt.c:753:32: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
ParseConfigGeneric = &ParseCore;
^
../src/core/time_mgmt.c:757:32: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
ParseConfigGeneric = &ParseGnss;
^
../src/core/time_mgmt.c:761:32: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
ParseConfigGeneric = &ParseEaf;
^
../src/core/time_mgmt.c:765:32: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
ParseConfigGeneric = &ParsePps;
^
../src/core/time_mgmt.c:769:32: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
ParseConfigGeneric = &ParseImu;
The code does compile and seems to work correctly, though. I looked up similar questions, but the problem is always that the pointer type differs from the original function's, but in this case they are all void* and the arguments match, so I can't tell what the problem is.
The call is as follows (no complaints from the compiler and I checked that the correct function gets called every time):
(*ParseConfigGeneric)(num_param, config_param);
The type of the second argument differs between the functions, and the function-pointer variable.
In the functions it's a pointer to const, which it isn't in the function-pointer variable.
The type needs to be exactly equal.

passing char array as function parameters in C

I want to copy arr2 to arr and pass arr as a function paramater
void func(char * array)
{}
int main(void)
{
int a;
char arr[6][50];
char arr2[][50]={"qweeeaa","bbbb","ffaa","eeaa","aaaa","ffaa"};
for(a=0; a<6;a++)
{
strcpy(arr[a], arr2[a]);
}
func(arr);
return 0;
}
But I can not pass arr as a function parameter. I get
[Warning] passing argument 1 of 'func' from incompatible pointer type [enabled by default]
[Note] expected 'char *' but argument is of type 'char (*)[50]'
I am using MinGW GCC 4.8.1
The type you pass and the type the function expects do not match. Change the function to receive a pointer to an array:
void func(char (*array)[50])
{
}
Other problems:
1) You haven't declared a prototype for func() either. In pre-C99 mode, compiler would assume the function returns an int and this would cause problem.
In C99 and C11, missing prototype makes your code invalid. So either declare the prototype at the top of the source file or move the function above main().
2) Include appropriate headers (<stdio.h> for printf etc).

Expect 'struct netif *' but argument is of type 'struct netif *' [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I get the following error with gcc when I declare a struct netif * from a function scope (where the compile doesn't complain) to global scope:
src/main.c:114:3: warning: passing argument 1 of 'low_level_init' from incompatible pointer type [enabled by default]
src/main.c:62:13: note: expected 'struct netif *' but argument is of type 'struct netif *'
Why is does compiler give the following "non-sensical" complaint?
expected 'stuct netif *' but argument is of type 'struct netif *'
This "full program"
void foonetif(struct netif *dst) {
if (dst) return;
return;
}
struct netif {
double bar;
};
int main(void) {
struct netif *netif = 0; /* NULL */
foonetif(netif);
return 0;
}
generates this output from gcc 10398683.c (gcc version 4.6.3), so with all default options
10398683.c:1:22: warning: ‘struct netif’ declared inside parameter list [enabled by default]
10398683.c:1:22: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]
10398683.c: In function ‘main’:
10398683.c:12:3: warning: passing argument 1 of ‘newnetif’ from incompatible pointer type [enabled by default]
10398683.c:1:6: note: expected ‘struct netif *’ but argument is of type ‘struct netif *’
Note the last warning (really a note) :)
The problem is scope. The first struct netif is in the scope of the function's argument list, and goes out of scope after that function ends. The second struct netif is defined in a new scope. These are thereby different structure types with different tags which happen to have the same name. Just like int i; and int i; in two different functions are different variables that happen to have the same name.
An interesting question; have fallen foul of this myself; mostly due to horrid hacks involving dubious type casts on innocent memory-blocks.
This answer is really just a corollary to R's answer, which pretty much nails the issue (though i'm not quite sure about the and goes out of scope after that function ends.. bit)
For me, the key to this is perusal of:
(1) ISO C99 6.7.2:
Two types have compatible type if their types are the same. Additional
rules for determining whether two types are compatible are described
in 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in
6.7.5 for declarators.46) Moreover, two structure, union, or enumerated types declared in separate translation units are compatible
if their tags and members satisfy the following requirements: If one
is declared with a tag, the other shall be declared with the same tag. ...
(2) C namespaces
Anyway, here's some code (~a couple of translation units) that hopefully demonstrates some possibly surprising behaviour for those that haven't yet hit this issue before:
blah.c:
#include <stdio.h>
struct bar {int a; int b;} stbar;
struct bar_ {int a; int d;} stbar_;
void foo(struct bar* pst);
void foo_(struct bar st);
void callfoo()
{
/*no warnings; possibly surprising results ! */
stbar.a=313;
stbar.b=31313;
foo(&stbar);
printf("called foo() with stbar: %d, %d\n", stbar.a, stbar.b);
/*generates incompatible types warnings:
blah.c:23:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
blah.c:6:6: note: expected ‘struct bar *’ but argument is of type ‘struct bar_ *’ */
stbar_.a=313;
stbar_.d=31313;
foo(&stbar_);
printf("called foo() with stbar_: %d, %d\n", stbar_.a, stbar_.d);
/*generates incompatible types warnings:
blah.c:31:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
blah.c:6:6: note: expected ‘struct bar *’ but argument is of type ‘struct bar *’ */
struct bar {float s; float t;} stbar;
foo(&stbar);
printf("called foo() with locally defined stbar: %f, %f\n", stbar.s, stbar.t);
}
void callfoo_()
{
stbar.a=313;
stbar.b=31313;
//passing in incompatible type by value ~ no warnings; possibly surprising results !
foo_(stbar);
/*uncomenting next line generates compiler error:
blah.c:47:5: error: incompatible type for argument 1 of ‘foo_’
blah.c:7:6: note: expected ‘struct bar’ but argument is of type ‘struct bar_’ */
//foo_(stbar_);
}
void main()
{
callfoo();
callfoo_();
}
blah_.c:
#include <stdio.h>
struct bar {int x; float z;} stbar;
void foo(struct bar* pst)
{
printf("foo : %d, %f\n", pst->x, pst->z);
pst->x=13;
pst->z=13.13;
}
void foo_(struct bar st)
{
printf("foo_ : %d, %f\n", st.x, st.z);
st.x=13;
st.z=13.13;
}
output:
$ gcc blah.c blah_.c
blah.c: In function ‘callfoo’:
blah.c:23:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
blah.c:6:6: note: expected ‘struct bar *’ but argument is of type ‘struct bar_ *’
blah.c:31:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
blah.c:6:6: note: expected ‘struct bar *’ but argument is of type ‘struct bar *’
$ ./a.out
foo : 313, 0.000000
called foo() with stbar: 13, 1095898235
foo : 313, 0.000000
called foo() with stbar_: 13, 1095898235
foo : 13274075, 0.000000
called foo() with locally defined stbar: 0.000000, 13.130000
foo_ : 313, 0.000000
$ gcc --version
gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 ...
Corollary of corollary: praise the gods for C++ namespaces.
Your "full program" wont compile.
struct netif is not declared before foonetif which uses it. Try moving the struct definition before its first use.

Resources