C语言中函数指针

函数调用的方法有两种分别如下:

void Fun(void)
{
    //do something
}

int main(void)
{
   ...
   Fun();
   ...
   return 0;
}
void Fun(void)
{
  //do something
}

int main(void)
{
   ...
   void (*p)(void);
   p=Fun;
   p();
   return 0;
}

上面两种方式都可以调用函数,第二种方式在回调函数中用的最多,尤其是在操作系统的任务切换中。那么我们就重点来分析下第二种方式。

第二种方式申明了一个函数指针p,那为啥写成void(*p)(void)?为啥不直接写成*p,不是说了函数名就是该函数的入口地址,为啥不直接把该地址传给指针呢,这样既好理解又方便省事,其实这样想不无道理,但是在C语言中有变量类型这个东东,比如int赋值给char,编译器就会报错,同样的道理函数也有类型,那么既然函数有类型,我们如何知道变量类型呢。现在写一个程序如下,注意,程序有错误,这个错误是故意写的,目的就是让编译器报错,使用编译器为gcc。

#include "stdio.h"

void Fun(void)
{
    printf("hello world");
}

int main(void)
{
    void *p;
        p=Fun;
    return 0;
}

下面是编译器输出:

g++.exe -x c++ -c C:\Users\Administrator.SC-201903191934\Desktop\unknown1.c -o C:\Users\Administrator.SC-201903191934\Desktop\unknown1.o -Wall -fpermissive -Wno-sign-compare -g
C:\Users\Administrator.SC-201903191934\Desktop\unknown1.c: In function `int main()‘:
C:\Users\Administrator.SC-201903191934\Desktop\unknown1.c:12: warning: invalid conversion from `void (*)()‘ to `void*‘

编译器报错意思是不能讲void (*)()类型转化为void *类型。这个警告就说明了函数Fun的类型是(*)()类型,而申明的指针类型是*,两个类型不一致,故导致其错误,既然这样,那么如何申请一个指针类型为(*)()的呢?C语言中给了函数指针这个类型,即(*)()类型,因此为了让指针指向一个函数地址,只需要声明一个(*)()类型即可。

如下:

#include "stdio.h"

void Fun(void)
{
    printf("hello world"); 

 } 

int main(void) {     void (*p)(void); //函数指针     p=Fun; return 0; }

这样就将函数Fun的地址给指针p了,与其说p是一个函数指针,倒不如说p是一个函数名,只是没有什么其函数内部,这里可以从旧式的函数申明上可以看出。

因此要运行这个所谓的函数p,只需要和函数使用一样就行,p();

现在再来看一个代码:

void *Fun(void)
{
    printf("hello world");
    return NULL;
}

这里函数Fun改为了有返回值的函数,其返回值为指针void *类型,那么我们如何来声明一个指针指该函数呢?

从上门面分析可以看出,该函数的类型应该是*(*)();所以现在我们需要声明一个相同类型的指针,即void *(*p)(void);这样就只需要p=Fun;就可以达到目的了。

#include "stdio.h"

void *Fun(void)
{
    printf("hello world");
    return NULL;
}

int main(void)
{
    void *(*p)(void);
    p=Fun;
    return 0;
}

总结:1. 函数名也是有类型的,因此在C语言中,必须严格遵守类型匹配原则。

           2. 函数名的类型为(*)()类型,如果有返回值,则在最前面增加返回类型即可,例如

               int * *Fun(int,int );其函数类型为**(*)(int,int),对应的函数指针为int **(*p)(int,int);

原文地址:https://www.cnblogs.com/listenscience/p/10991250.html

时间: 2024-10-17 14:20:55

C语言中函数指针的相关文章

C语言中函数指针数组浅析

发现问题 问题分析 示例代码 发现问题 今天,在阅读Linux内核中关于socket的源代码时,遇到了下面一段代码: struct proto_ops { int family; struct module *owner; int (*release) (struct socket *sock); int (*bind) (struct socket *sock, struct sockaddr *myaddr, int sockaddr_len); int (*connect) (struct

c语言中函数指针和指针函数

一.什么是函数指针: 函数指针本质上也是指针,我们所写函数代码在内存中会被分配一段专门的储存空间,这段储存空间的地址就是函数的地址,既然是地址,就可以用指针去表示,自然就有了函数指针. 二.函数指针的用法: 1.首先明确函数指针怎么申明.形如:返回值类型 (*变量名)(参数类型1,参数类型2,...) 例如 int (*p) (int,int) 2.我们还需要了解如何通过指针调用函数. (*p)(3,5); 3.如何给该类型的指针赋值: 非常简单,直接将函数名赋给指针即可,因为函数名即为函数的首

C语言中函数指针与指针函数的区别和实际应用

1.指针函数 指针函数是返回指针的函数,主体是函数,返回值是一个指针   基本声明形式:返回数据类型 + * + 函数名 + (变量类型1,…); int* fun(int,int); int * fun(int,int); int *fun(int,int); 这三种声明都可以,第一种更加直观 返回值是 int* 类型. #include<stdio.h> int* fun(int* x) //传入指针 { int* tmp = x; //指针tmp指向x return tmp; //返回t

C语言中函数和指针的参数传递

最近写二叉树的数据结构实验,想用一个没有返回值的函数来创建一个树,发现这个树就是建立不起来,那么我就用这个例子讨论一下c语言中指针作为形参的函数中传递中隐藏的东西. 大家知道C++中有引用的概念,两个数据引用同一个数据,那么更改任意的一个都相当于更改了本体,那么另一个数据所对应的值也会改变,可是C中是没有这个概念的.所以就产生了一些东西.和我们本来想的有差别. 一.明确C语言中函数的入口: C语言中函数的形参负责接收外部数据,那么数据究竟怎么进入函数的呢,其实我们在函数体内操作的形参只是传递进来

从头开始-05.C语言中函数

函数: 完成特定功能代码段 特点:函数只有调用的时候才会执行 定义格式:返回值类型 函数名称(形参类型 形参名称,...){ 语句; ...  } 函数参数 形式参数:在定义函数的时候,函数名后面小括号中的参数 实际参数:在函数调用的时候,函数名后面小括号中的参数 注意点: 形参与实参必须一一对应 实参与形参的类型必须一致 基本数据类型作为函数参数传递是值传递 组作为函数参数传递是地址传递 指针作为函数参数传递是地址传递 结构体作为函数参数传递是值传递 返回值: return 作用: 1.结束函

汇编语言的寻址方式与C语言中的指针是一个东西。

汇编语言的寻址方式与C语言中的指针是类似的! 汇编语言的寻址方式与C语言中的指针:寻找数据的方法. 指针就是存了 变量的地址,寻址方式就是得到保存变量的地址. 当你学了汇编语言,你就知道为什么C语言有函数指针,为什么函数要以return 结尾.为什么main()函数为程序的入口. 给我的感觉就是C语言是汇编语言的进化版本.因为C语言处处都有着汇编语言的影子. 一个小小的建议:先学习汇编语言.自学书籍是 清华大学 王爽的 汇编语言.之后,学习C语言,自学书籍,我还真不好推荐,我用的是C语言入门经典

如何理解c语言中得指针

最近有学习了c语言中得指针知识,脑袋都大了,迷迷糊糊理解了一半,由自己查了下资料,跟大家分享下c语言中指针的基本知识吧: 1.指针是一个地址,指向的是个类型. 2:指针指向的是地址,地址指向的是内容. 我们需要一个变量,来存储地址,这个变量的值是地址,但是我们可以通过修改变量的值,来不断的改变地址,但是,我们如果需要改变该个地址的值的话,就需要,对地址的值进行修改,而不改变地址. int a = 10: int *p : p = &a: *p =11: a=? 这里我们看到,p 是一个变量,我们

C中函数指针的用法

理解了C中的声明和指针的话题后再来看函数指针的用法就很容易了. C中函数指针主要有两个用途: 1.作为参数传递给另外一个函数(即作为回调函数) 2.转换表(jump table) 下面分别来介绍作为回调函数的用法和作为转换表的用法 1.回调函数 在链表的查找中使查找函数与类型无关 /*在一个单链表中查找一个指定值的函数.它的参数是一个指向链表第一个节点的指针 * 一个指向我们需要查找的值的指针和一个函数指针,它所指向的函数用于比较存储于链表中的类型的值*/ #include <stdio.h>

C语言中函数返回数组

#include "stdio.h"/*int* set(int a,int *c){ int *b; b=malloc(sizeof(int)*3); c[0]=a; c[1]=1+a; c[2]=2+a; b[0]=13; b[1]=14; b[2]=15; return b;}*/char *set(void){ char *buf; buf=malloc(sizeof(char)*3);//创建内存区 buf[0]=0x30; buf[1]=0x31; buf[2]=0x32;