函数指针声明
Function Pointer Declaration
与我在网上找到的示例、SO 答案和教程相比,我对我使用的教科书有点困惑。
书中的代码声明了两个函数指针,但从未给它们赋值,并且在声明中没有使用 *
。代码运行良好,编译时没有警告,所以我有点困惑。
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
void f(int), g(int);
signal(SIGUSR1, f);
signal(SIGUSR2, g);
while(1)
sleep(1);
}
void f(int signum)
{
printf("Recieved signal %d: SIGUSR1\n", signum);
}
void g(int signum)
{
printf("Received signal %d: SIGUSR2\n", signum);
exit(SIGUSR2);
}
我在网上找到的代码看起来都与此类似,指针语法 *
并且将函数地址显式分配给函数指针:
#include <stdio.h>
void fun(int a)
{
printf("Value of a is %d\n", a);
}
int main()
{
void (*fun_ptr)(int) = &fun;
(*fun_ptr)(10);
return 0;
}
是否有不止一种声明函数指针的正确方法?
为什么书中的代码有效?
一个版本比另一个版本“更正确”吗?
这个声明
void f(int), g(int);
在函数 main 的块范围内声明了两个函数 f
和 g
。它们可以在 main 之前声明,但代码的作者决定在 main 中声明它们,因为它们只在 main 中使用。所以没有函数指针的声明。
看来你对函数声明的地方搞糊涂了
为了更清楚,您可以按以下方式重写程序
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
void f(int), g(int);
// or
void f(int);
void g(int);
int main(int argc, char *argv[])
{
signal(SIGUSR1, f);
signal(SIGUSR2, g);
while(1)
sleep(1);
}
void f(int signum)
{
printf("Recieved signal %d: SIGUSR1\n", signum);
}
void g(int signum)
{
printf("Received signal %d: SIGUSR2\n", signum);
exit(SIGUSR2);
}
尽管编译器会发出一条消息,指出存在冗余函数声明,但该程序是有效的。
这些语句中使用的函数指示符
signal(SIGUSR1, f);
signal(SIGUSR2, g);
被编译器隐式转换为指向函数的指针。
void f(int), g(int);
不声明函数指针*。它声明了两个函数(f
接受int
并返回void
,g
接受int
并返回void
)。
(void (*f)(int), (*g)(int);
会声明相应的函数指针,这些函数指针确实需要在使用前进行一些初始化。)
在块范围内声明函数有点令人困惑,因为函数不能是块局部的。
实际上就好像你在文件范围内有 void f(int); void g(int);
,只是块范围限制了前向声明的范围:
示例:
void call_f(void)
{
void f(int);
f(42);
}
void call_f_again(void)
{
void f(int); //need to redeclare unless there's also a global decl for f
f(42);
}
但是当涉及到函数时,这个范围限制实际上没有任何作用,因为所有这些重新声明必须相互兼容并与相应的文件范围声明(无论是否提供)相兼容。
在文件范围简单地声明函数是最简单的(也是最不容易混淆的)。
void f(int)
仅在用作函数参数时等同于 void (*f)(int)
。这类似于函数参数中的 int f[]
等价于 int *f
. 的方式
与我在网上找到的示例、SO 答案和教程相比,我对我使用的教科书有点困惑。
书中的代码声明了两个函数指针,但从未给它们赋值,并且在声明中没有使用 *
。代码运行良好,编译时没有警告,所以我有点困惑。
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
void f(int), g(int);
signal(SIGUSR1, f);
signal(SIGUSR2, g);
while(1)
sleep(1);
}
void f(int signum)
{
printf("Recieved signal %d: SIGUSR1\n", signum);
}
void g(int signum)
{
printf("Received signal %d: SIGUSR2\n", signum);
exit(SIGUSR2);
}
我在网上找到的代码看起来都与此类似,指针语法 *
并且将函数地址显式分配给函数指针:
#include <stdio.h>
void fun(int a)
{
printf("Value of a is %d\n", a);
}
int main()
{
void (*fun_ptr)(int) = &fun;
(*fun_ptr)(10);
return 0;
}
是否有不止一种声明函数指针的正确方法?
为什么书中的代码有效?
一个版本比另一个版本“更正确”吗?
这个声明
void f(int), g(int);
在函数 main 的块范围内声明了两个函数 f
和 g
。它们可以在 main 之前声明,但代码的作者决定在 main 中声明它们,因为它们只在 main 中使用。所以没有函数指针的声明。
看来你对函数声明的地方搞糊涂了
为了更清楚,您可以按以下方式重写程序
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
void f(int), g(int);
// or
void f(int);
void g(int);
int main(int argc, char *argv[])
{
signal(SIGUSR1, f);
signal(SIGUSR2, g);
while(1)
sleep(1);
}
void f(int signum)
{
printf("Recieved signal %d: SIGUSR1\n", signum);
}
void g(int signum)
{
printf("Received signal %d: SIGUSR2\n", signum);
exit(SIGUSR2);
}
尽管编译器会发出一条消息,指出存在冗余函数声明,但该程序是有效的。
这些语句中使用的函数指示符
signal(SIGUSR1, f);
signal(SIGUSR2, g);
被编译器隐式转换为指向函数的指针。
void f(int), g(int);
不声明函数指针*。它声明了两个函数(f
接受int
并返回void
,g
接受int
并返回void
)。
(void (*f)(int), (*g)(int);
会声明相应的函数指针,这些函数指针确实需要在使用前进行一些初始化。)
在块范围内声明函数有点令人困惑,因为函数不能是块局部的。
实际上就好像你在文件范围内有 void f(int); void g(int);
,只是块范围限制了前向声明的范围:
示例:
void call_f(void)
{
void f(int);
f(42);
}
void call_f_again(void)
{
void f(int); //need to redeclare unless there's also a global decl for f
f(42);
}
但是当涉及到函数时,这个范围限制实际上没有任何作用,因为所有这些重新声明必须相互兼容并与相应的文件范围声明(无论是否提供)相兼容。
在文件范围简单地声明函数是最简单的(也是最不容易混淆的)。
void f(int)
仅在用作函数参数时等同于void (*f)(int)
。这类似于函数参数中的int f[]
等价于int *f
. 的方式