给定指定类型定义与函数,问询call( (Bar) foo);调用的含义
解读
call( (Bar) foo);的含义 咱们一步步拆解来看这个调用到底在干啥,先把前置的类型和函数定义都理清楚:
先搞懂各个前置定义
typedef int (*Bar)(void *, int a);:这是给一种函数指针类型起了个简洁的别名Bar。说白了,Bar类型的指针,指向的函数必须满足:接受两个参数(第一个是通用指针void*,第二个是int),返回值是int。int foo (Struct *s, int b);:这是个普通的业务函数,它接受一个自定义结构体指针Struct*和一个int参数,执行完逻辑后返回int结果。void *call(Bar c);:call是个“函数指针处理器”函数——它接收一个Bar类型的函数指针作为参数,内部会调用这个传入的函数,最后返回一个void*类型的结果(可能是函数调用的返回值转的,也可能是其他关联内存地址)。
核心调用call( (Bar) foo);的含义
这个调用分两个关键步骤:
- 强制类型转换
(Bar) foo:把foo的函数指针转换成Bar类型。为啥要转?因为foo的第一个参数是Struct*,而Bar要求的第一个参数是void*——好在C语言里,任何对象指针都可以安全转换成void*,再转换回原类型也没问题,所以这个转换是合法的(前提是后续调用时传入的void*确实是Struct*类型的指针,不然会出问题)。 - 调用
call函数:把转换后的foo函数指针传给call。接下来call函数内部会做的事情,大概率是调用这个传入的函数指针c(也就是转换后的foo),传入符合Bar类型要求的参数(比如某个Struct*转成的void*,加上一个int值),然后把调用的结果(或者和调用相关的内存地址)包装成void*返回给调用者。
要注意的风险点
- 如果
call内部调用c时,第一个参数不是Struct*类型转来的void*,那foo里操作这个指针就会触发未定义行为,比如内存访问错误、程序崩溃。 - 函数指针转换本身是C标准允许的,但只有当转换回来的类型和原函数类型完全一致时,调用才是安全的。这里的场景刚好符合:
foo被转成Bar后,调用时传入的void*其实是Struct*,相当于隐式转回去了,所以只要参数传递正确,就是安全的。
内容的提问来源于stack exchange,提问作者fura95
相关产品推荐
相关产品推荐

