klu*_*utt 5 c function-pointers function-prototypes
我看到一个被标记为欺骗的问题,但是该问题的一部分没有得到欺骗的回答,并且我没有找到合适的欺骗来纠正它。所以去。
我曾经看到这样的声明:
int (*function)(int, float);
Run Code Online (Sandbox Code Playgroud)
我不太了解 它有两个参数,但没有名称。这是如何运作的?我的意思是,在声明这样的函数时:
int f(int x, int y) {
return x+y;
}
Run Code Online (Sandbox Code Playgroud)
没有标识符怎么办?我注意到这行不通,甚至在第一行给出了一个编译器错误,说
int f(int, int) {
return /* What should I even write here? */ ;
}
Run Code Online (Sandbox Code Playgroud)
我得到两个错误:
f.c:1:7: error: parameter name omitted
int f(int, int)
^~~
f.c:1:7: error: parameter name omitted
int f(int, int)
^~~
Run Code Online (Sandbox Code Playgroud)
It can easiest be explained with function prototypes. A function prototype declares a function but does not define it.
One purpose of prototypes is that it makes it possible with different compilation units. You put the prototypes in a header file and the definition in the source file. This makes it possible to compile an object file. When you then include the header file and link with the object file, you don't need to recompile the functions.
They are also useful if you for some reason want two functions to call each other. Consider this example:
void fun1(void) {
fun2();
}
void fun2(void) {
fun1();
}
Run Code Online (Sandbox Code Playgroud)
Sure it would be an endless loop, but the point is that this would not compile. fun2 would compile, but when we come to fun1 we don't know that fun2 exists. The solution is to use function prototypes.
void fun2(void);
void fun1(void) {
fun2();
}
void fun2(void) {
fun1();
}
Run Code Online (Sandbox Code Playgroud)
When you see that this is the purpose, it is quite obvious that function prototypes is just a declaration. It does not do anything. The declaration int f(float, char*); simply says that there exists a function with the name f. It returns an int, and it takes float and a char* as argument. So for your question, since it never do anything with the parameters, it does not need to have a name to reference them by. Only the definition does. That's why you can get the compiler error error: parameter name omittedthat you posted in the question:
Your example is not a function, but a function pointer. The same reason applies there. You can make a function pointer point at a function, but it is only the function definition that needs identifiers for the parameters. Read more about function pointers here
You can actually use different names for the parameters in the declaration and definition if you want. One potential use for this (I'm not saying if it is good or bad. Just showing that it's possible) is to use descriptive names for the variables in the prototype but shorter in the definition. This compiles well for example:
void backwards(const char *inputString, char *outputString);
void backwards(const char *is, char *os) {
size_t l = strlen(is);
for(size_t n=0; n<l; n++)
os[l-n-1]=is[n];
os[l]='\0';
}
Run Code Online (Sandbox Code Playgroud)
One valid reason to to this is that the header file is usually used as an interface, so it makes sense to say that the identifiers have to be more descriptive there. Again, I'm just showing that it is possible and does not say that you should or should not do this.
While speaking of prototypes, it can be worth mentioning a fact many people don't know. The prototype void f(); does NOT declare a function taking no arguments. It declares a function taking an unspecified number of arguments. The correct way to declare a function taking no arguments is void f(void);. This can be important when it comes to function pointers. Look at this example that I copied from another answer I made:
$ cat main.c
int foo() { return 0; }
int bar(int a) { return a; }
int main(void)
{
int (*f)();
f=foo;
f=bar;
int(*g)(void);
g=foo;
g=bar;
}
Run Code Online (Sandbox Code Playgroud)
This generates this warning:
$ gcc main.c
main.c: In function ‘main’:
main.c:11:3: warning: assignment to ‘int (*)(void)’ from incompatible pointer type ‘int (*)(int)’ [-Wincompatible-pointer-types]
g=bar;
^
Run Code Online (Sandbox Code Playgroud)
When it comes to regular function prototypes, you can skip the arguments completely if you wish. This compiles and runs just fine:
void foo();
int main() {
foo(5,6);
}
void foo(int x, int y) {
printf("The sum is: %d\n", x+y);
}
Run Code Online (Sandbox Code Playgroud)
The above does not work in C++, as C++ does not support prototypes with unspecified arguments. In C++, void f(); is exactly the same thing as void f(void);. This is the reason why C cannot support function overloading while C++ can.
Lastly, one compiling example with the snippet you provided:
// Declaration of function pointer
int (*function)(int, float);
// Declaration of function
int foo(int, float);
// Definition of function
int foo(int x, float y) {
return x;
}
// Assign the function pointer
function = foo;
Run Code Online (Sandbox Code Playgroud)
You can basically declare a function prototype in two (excluding variadic functions) ways:
<return type> <name>(); which declares a function with unspecified arguments, and will fit with any function definition with proper name and return type, irregardless of the arguments.<return type> <name>(<type> [<name>], <type> [<name>] ... );声明具有指定参数类型的函数。名称不是强制性的,可以与定义中的名称不同。声明不带参数的函数的正确方法是<return type> <name>(void);