理解(*(void(*)())0)()和void (*signal(int, void(*)(int)))(int)

本文详细解析了C语言中的复杂表达式,如(*(void(*)())0)()及void(*signal(int,void(*)(int)))(int)。通过优先级规则拆解函数指针的声明与使用,并提供了signal函数的具体应用实例。

1.分析(*(void(*)())0)()

   借助《C专家编程》上的优先级规则思想+《C陷阱与缺陷》的分析

优先级规则:

A  声明从它的名字开始读取,然后按照优先级顺序依次读取。

B  优先级从高到低依次是:

     B.1  声明中被括号括起来的那部分

     B.2  后缀操作符:括号()表示这是一个函数,而方括号[]表示着是一个数组。

     B.3  前缀操作符:星号*表示“指向...的指针”。

C  如果const和(或)volatile关键字的后面紧跟类型说明符(如 int,long等),那么它作用于类型说明符。在其他情况下,const和(或)volatile关键字作用于它左边紧邻的指针星号。

对本例来说

可将本例分成(*(void(*)())0)和()

       (1)(*(void(*)())0),由于后缀是(),表明(void(*)())0是一个函数指针

       (2)(void(*)())0分成(void(*)())和0,关键就在于这个void(*)()是什么类型

       通常一个函数指针定义是类型 (*函数指针名)(参数),如void (*h)();表示h是一个指向返回值为空类型的函数的指针。

        因此,void (*)()表示一个“指向返回值为浮点类型的函数的指针”的类型转换符。那么(void(*)())0表示对0地址进行该类型转换。然后(*(void(*)())0)()就表示对0地址强转类型后的函数调用

2.分析void (*signal(int, void(*)(int)))(int)

       同样可以用上述优先级定理来分析,signal(int, void(*)(int))为指向返回类型为空类型,参数为int类型的函数的指针。

       值得注意的是,比如void (*sfp)(int);sfp为函数指针,但当sfp被signal(int, void(*)(int))代替时,必须保证signal函数的返回类型也是void型,且该函数的解释是传递适当的参数以调用signal函数,调用这个指针函数会先直接执行signal函数,必须保证参数一致,然后signal返回一个指向调用前的用户定义的信号处理函数的指针(还没弄明白之后怎么用的),然后再传递一个整型参数调用signal返回后的函数指针所指向的函数。

        void (*signal(int, void(*)(int)))(int)实际上是signal信号处理函数原型,在signal.h头文件中,signal函数接收两个参数:一个整型的信号编码,代表“被捕获”的特定signal,另一个是指向用户提供的函数的指针,该函数用于处理“捕获到”的特定signal。

这里参照一个例子来说明这个函数的用法:



运行结果:


      简单说明下,signal函数调用后将一直保持接收信号状态,而alarm函数将在5秒后发送一个SIGALRM信号,signal函数捕捉到这个信号就会调用handler函数(handler函数可以自己定义)。



### 中断处理函数的定义与用法 在C语言中,中断处理函数的定义通常涉及函数指针特定的关键字(如 `interrupt`)。以下是对 `void (*INT_InterruptHandler)(void)` 的定义与用法的详细说明。 #### 1. 定义 `void (*INT_InterruptHandler)(void)` 是一个指向返回值为 `void`、无参数的函数的指针。这种定义方式允许将一个函数赋值给该指针,并通过指针调用该函数[^1]。 例如: ```c void myInterruptHandler(void) { // 中断处理逻辑 } void (*INT_InterruptHandler)(void) = myInterruptHandler; ``` 如果需要定义一个中断处理函数,可以结合特定硬件平台的关键字(如 `interrupt`)来实现。例如,在某些嵌入式系统中,可能使用如下定义[^2]: ```c typedef interrupt void (*PINT)(void); PINT INT_InterruptHandler = myInterruptHandler; ``` 这里,`interrupt` 关键字表示该函数是一个中断服务程序,具体行为取决于编译器硬件平台的支持[^3]。 #### 2. 用法 中断处理函数的典型用法包括以下几个方面: - **声明与赋值**:首先声明一个函数指针类型,然后将其赋值为具体的中断处理函数。 - **调用**:通过解引用函数指针来调用对应的中断处理函数。 - **绑定到硬件中断**:将函数指针绑定到硬件中断向量表中,确保在发生中断时自动调用该函数。 示例代码如下: ```c // 声明一个中断处理函数 void myInterruptHandler(void) { // 处理中断逻辑 // 恢复状态 } // 定义函数指针 void (*INT_InterruptHandler)(void) = myInterruptHandler; // 调用中断处理函数 (*INT_InterruptHandler)(); ``` 对于嵌入式系统中的中断处理函数,还需要注意以下几点: - 确保函数没有参数且返回值为 `void`。 - 在函数内部保存恢复寄存器状态,以避免影响主程序运行。 - 使用特定的头文件(如 `interrupt.h` 或 `signal.h`),以支持中断相关的关键字功能[^3]。 #### 3. 示例:结合硬件平台的中断定义 以下是一个典型的嵌入式系统中断定义示例: ```c #include <interrupt.h> // 引入中断支持头文件 // 定义中断处理函数类型 typedef interrupt void (*PINT)(void); // 实现中断处理函数 interrupt void myInterruptHandler(void) { // 中断处理逻辑 } // 定义函数指针并赋值 PINT INT_InterruptHandler = myInterruptHandler; // 将中断处理函数绑定到中断向量表 void bindInterruptHandler() { PIE_VECT_TABLE.PIE1_RESERVED = INT_InterruptHandler; } ``` ### 注意事项 - 中断处理函数必须高效,避免长时间占用CPU资源。 - 确保中断处理函数的声明与实际定义一致,否则可能导致链接错误或运行时问题。 - 在某些平台上,可能需要额外配置中断优先级或使能中断。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值