我遇到了以下代码片段,我有两个问题想要求帮助:
//This is the function poiner
int (*OnDataAvail)( int *, int *, int * )
//This is the function header
int ReqHandler_pack(int *vc ATTRIBUTE((unused)),
int *req, int *complete ATTRIBUTE((unused)), void* stream)
if((*request)->dev.OnDataAvail == ReqHandler_pack) {
第一: 这部分代码有一个编译器警告: 警告:不同指针类型的比较缺少强制转换[默认启用]
然后我将其更改为
if((int *)(*request)->dev.OnDataAvail == (int *)ReqHandler_pack)
通过更改此信息,警告不存在。但是,我不确定它为什么会起作用。
另一个问题是:函数指针需要具有相同数量的参数吗?
答案 0 :(得分:2)
是的,两个函数指针需要具有兼容(或指定)的兼容签名(用于指向函数)。这意味着相同的arity(参数数量)和每个等级和相同结果类型的兼容类型的参数。
给定的实现可能有ABI指定不同的calling conventions(对于不同签名的函数)。
两个函数指针按位相等这一事实取决于实现(当然,某些例程foo
的地址等于相同例程foo
的地址, 相同签名的两个不同函数比较不等。)
这是为了允许在机器级别具有不同方式或指令的实现,以根据其签名调用某些C函数。例如,通过寄存器或机器堆栈传递参数,使用不同的跳转或调用机器指令或使用不同的库或空格代码等...但是,我不知道任何这样奇怪的实现......
答案 1 :(得分:1)
它通过偶然的方式起作用 具体来说,因为你的实现说所有的指针类型(代码,数据(void,struct,...))都是往返的转换兼容(使用,然后再回到正确的类型之前)否则)。所有现代桌面都这样做(x86至少在平面内存模式下),但只有一些微控制器。
为明确定义的行为要做的是将这些函数指针转换为相同的函数指针类型(所有函数指针类型都是往返转换兼容)。
即使这样,也不能保证任何两个函数指针都不相等。
6.3.2.3指针
1 指向
void
的指针可以转换为指向任何对象类型的指针。指向任何对象类型的指针可以转换为指向void
并再次返回的指针;结果应该等于原始指针。
2对于任何限定符 q ,指向非 q - 限定类型的指针可以转换为指向 q - 限定版本的指针类型;存储在原始指针和转换指针中的值应相等 3值为0的整型常量表达式,或类型void*
的表达式,称为空指针常量。 宏NULL
在<stddef.h>
(和其他标头)中定义为空指针常量;见7.19。如果将空指针常量转换为指针类型,则保证将结果指针(称为空指针)与指向任何对象或函数的指针进行比较。 4将空指针转换为另一种指针类型会产生该类型的空指针。任何两个空指针都应该相等 5整数可以转换为任何指针类型。除非先前指定,否则结果是实现定义的,可能未正确对齐,可能不指向引用类型的实体,并且可能是陷阱表示。 用于将指向整数或整数的指针转换为指针的映射函数旨在与执行环境的寻址结构一致。
6任何指针类型都可以转换为整数类型。除了之前指定的以外,结果是实现定义的。如果结果无法以整数类型表示,则行为未定义。结果不必在任何整数类型的值范围内 7 指向对象类型的指针可以转换为指向不同对象类型的指针。如果结果指针未正确对齐通常,“正确对齐”概念是可传递的:如果指向类型A的指针正确对齐指向类型B的指针,而指针又针对指针正确对齐要键入C,然后指向类型A的指针正确对齐,以指向引用类型的类型C。,行为未定义。否则,当再次转换回来时,结果将等于原始指针。当指向对象的指针转换为指向字符类型的指针时,结果指向对象的最低寻址字节。结果的连续递增,直到对象的大小,产生指向对象剩余字节的指针。
8 指向一种类型的函数的指针可以转换为指向另一种类型的函数的指针,然后再返回;结果将与原始指针进行比较。如果转换的指针用于调用类型与引用类型不兼容的函数,则行为未定义。
我强调要加以标记相关部分。