function definition without prototype - c

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);

Related

Why does having an `int (*)(float)` point to an `int foo()` trigger a warning, but having an `int (*)(double)` point to it doesn't?

I have this piece of code:
int foo() { return 0; }
int main()
{
int (*float_function)(float) = foo;
}
When compiled using x86-64 GCC 12.2, with -Wall, it produces the warning (Link):
warning: initialization of 'int (*)(float)' from incompatible pointer type 'int (*)()' [-Wincompatible-pointer-types]
But, when I change from float to double (Link):
int foo(){ return 0;}
int main()
{
int (*double_function)(double) = foo;
}
The warning is now gone.
But I think that both of these should get a warning.
Am I wrong somewhere? Why does GCC not complain about the second example?
int foo() is declared without specifying its parameters. This is an obsolescent feature that lets you call it with any arguments. When calling the function, integer arguments are promoted to int (if needed), and float arguments are promoted to double.
Due to this, it's impossible for this function to receive a float parameter, which makes it incompatible with int (*)(float), but not with int (*)(double).
If you want a function that takes no parameters, declare it as int foo(void) which will make it incompatible with both.
Note that even with double, the code is not valid C because int foo() {...} is a function definition, so the compiler knows that it has no parameters (see chux's comment below for the standard reference). Most compilers still allow it.
If you replace it with a declaration int foo(); and place the definition elsewhere then the above is correct. In that case, the relevant standard quote (C17 6.7.6.3/15) is:
For two function types to be compatible, [...] If one type has
a parameter type list and the other type is specified by a function declarator that is not part of a
function definition and that contains an empty identifier list, [...] the type of each parameter shall be compatible with the type that results from the application of the default argument promotions.

In C, can you omit the parameter types of a function pointer when initializing it with the address of a declared function?

I'm trying to make sure I understand the syntax for function pointers in C. I know it's just a pointer to a specific type. That being said, why does the following code compile and print '10'?
(Note I'm using GCC 9.4.0 on Ubuntu 20.04)
void f(int);
void (*foo)() = f;
int main(){
foo(10);
return 0;
}
void f(int n){
printf("%d\n", n);
}
Shouldn't we at least get a compile time warning: initialization of 'void(*)()' with incompatible pointer type 'void(*)(int)'? Is foo getting initialized to void(*)(int) based on f?
If I change 'void f(int)' to 'void f(float)' I do get a warning. If I add 3 more int params to f e.g. void f(int, int, int, int) it still compiles and runs fine. If I make the last param a float, another warning.
The rules are the same for function pointer declarations as for function declarations ; and a pointer to function with empty parentheses parameter list is compatible with a pointer to prototyped function, if the return type matches.
In your example the issues are equivalent to:
void g();
int main()
{
g(10);
}
void g(int) { ..... }
The rules are: you can declare a function with empty parentheses and call it with arguments, but in the function call, certain conditions must be met and it is undefined behaviour with no diagnostic required if those conditions are not met.
One of the "certain conditions" is that you cannot have float as a parameter type in the function definition. Another is that the type and count of arguments must match the type and count of parameters in the function definition. To repeat, no diagnostic is required for any of this; your compiler is going above minimum requirements by warning about the incorrect parameter type float.
The type of the function pointer foo:
void (*foo)()
Is a pointer to a function taking an unspecified number of parameters and returning void. So a pointer to any function that has a return type of void (assuming no parameters are subject to promotion, i.e. char, short, float) is compatible with foo and can be assigned to it.
If you instead defined it like this:
void (*foo)(void)
This would generate an error for an incompatible pointer type, as foo points to a function that takes no arguments and returns void, and f does not match that.

Array of structures of function pointers 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 *);

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).

pointer to a char

I have query on how to assign a pointer to a character
Sample program:
#include <stdio.h>
void main()
{
const char str1[]="MANCHESTER";
char *q;
q=str1;
*q='A';
printf("%s\n",q);
}
In the the above program, I am assigning a character pointer to string "str1",
When I compile the program with gcc, I get the below warning:
ptr3.c: In function ‘main’:
ptr3.c:7:3: warning: assignment discards qualifiers from pointer target type
I am not able to understand what the warning means.
warnings i get:
2: warning: return type of 'main' is not 'int'
: In function 'main':
7: warning: implicit declaration of function 'printf'
7: warning: incompatible implicit declaration of built-in function 'printf'
adding include stdio.h and return type int, fixes those.
#include <stdio.h>
int main()
{
char str1[]="MANCHESTER";
char *q;
q=str1;
*q='A';
printf("%s\n",q);
return 0;
}
edit:
i guess you should not declare the char array as const, if you plan on modifying it, directly or indirectly through another pointer

Resources