函数与函数指针

本文详细介绍了C/C++中的函数及函数指针概念,包括声明、赋值、调用等基本操作,并提供了实例帮助理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数声明
void func();/* 声明一个函数 */
•    格式: 返回值类型 函数名([形参列表]);
•    含义: 声明一个无返回值(void)、无参数的函数 func。
•    函数名: func是一个函数指示符(function designator,即函数名),它会自动转换为函数指针类型,指向函数的入口地址。
•    地址: func、&func、*func 在语义上都等价,表示函数的首地址。

函数指针声明
void (*init)();/* 声明一个函数指针 */
•    格式: 返回值类型 (*指针变量名) ([形参列表]);
•    含义: 声明一个函数指针 init,它可以指向一个返回值为 void、无参数的函数。
•    括号的必要性: (*init) 的括号不可省略,否则void *init() 会变成一个返回void*的函数声明,而不是函数指针。

函数指示符与函数指针的关系
•    C语言: 函数指示符(上文func)不是左值也不是右值,但在表达式中会自动转换为函数指针类型的右值。
•    C++: 函数指示符是左值,转换为右值的过程是左值到右值的转换。
•    赋值:可以用init = func;或init = &func;将函数地址赋给指针。
•    调用方式: 通过函数指针调用时,init() 和 (*init)() 等价,不需要显式解引用(*),因为编译器会自动处理。

类型匹配
•    函数指针的类型由 返回值类型 和 形参列表 共同决定。
示例
        void (*init1)() 和 void (*init2)(void *) 是不同类型的函数指针。
        混用可能引发警告(warning),甚至未定义行为(undefined behavior)。

示例解析
•    示例 1
        void (*init)(); /* 声明一个函数指针 */
        •    未初始化时,init的值未定义,可能指向随机地址。
        •    init = *init是未定义行为,因为init未初始化。
        •    &init 是 init 这个指针变量本身的地址。

•    示例 2
        声明函数:
        int abc(int a);//函数abc,返回类型int,形参int
        int abcd(int *a);// 函数abc,返回类型int,形参int *

        声明函数指针:
        int (*init1)(int);// 函数指针init1,返回类型int,形参int
        int (*init2)(int*);//函数指针init2,返回类型int,形参int *

        赋值:
        init1=abc;或者init1=&abc;
        init2=abcd;或者init2=&abcd;

        调用方式:
        *init1()或者init1()
        *init2()或者init2()

        由于函数指针init1和init2的返回值类型格式相同,init2=abc或者init1=abcd ,形参类型不匹配,会有warning但可能可以正常使用。

类型转换与 void*
void*区别于void (*)(),void*是一个通用指针类型,不能直接用于函数指针
(void *)可以用于强制类型转换为空指针类型
比如指针函数void *func(); 表示返回值是指针类型

(void (*)(void *))是将某个值强制转换为一个函数指针类型,指向的函数接受void*参数。

typedef 使用
typedef void(*FunType)();/* 定义一种函数指针类型的格式,函数指针类型别名FunType*/
Funtype init;//等价于 void (*init)(); 

函数指针的用途

•    函数指针允许将函数作为参数传递,从而实现更高的灵活性。
•    常用于回调函数、动态函数调用(如函数表)。

示例

void say_hello() {
    printf("Hello\n");
}
void call_func(void (*init)()) { /*void (*init)(); 声明参数名为init,类型是 void (*init)(),即一个指向无参数、返回值为 void 的函数的指针。*/
    init(); /*表示通过这个函数指针调用它所指向的函数*/
}
int main() {
call_func(say_hello); //输出"Hello"
    //call_func(say_hello) 将 say_hello 函数的地址传递给 call_func
    //say_hello 是一个函数指示符(函数名),函数名本身就代表该函数的地址,可以直接传递给 call_func
    //call_func 的参数f接收到 say_hello 的地址后,在函数中通过 init() 调用say_hello
    return 0;
}

注意事项
•    未初始化的函数指针使用前必须赋值,否则会导致未定义行为。
•    函数指针调用时,参数类型和数量必须与声明一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值