在下面的示例中,我对不应该包含参数的函数进行了CAST转换,该指针指向应接收参数的函数。假设它给出了预期的结果,那么此过程是否可能导致某些故障?在线测试:https://onlinegdb.com/SJ6QzzOKI
typedef void (*Callback)(const char*);
Callback cb;
void inserisce_cb(void* c) {
cb=c;
}
void esegue_cb(){
cb("pippo");
}
void scriveTitolo(const char* titolo) {
Uart_Println(titolo);
}
void scriveTitolo2() {
Uart_Println("pluto");
}
void main(){
inserisce_cb(scriveTitolo);
esegue_cb();
inserisce_cb(scriveTitolo2);
esegue_cb();
}
根据c 6.3.2.3 8,由c标准定义了将一个函数的指针转换为另一个函数的指针,但是使用结果指针来调用类型不兼容的函数并非如此:
可以将指向一种类型的函数的指针转换为指向另一种类型的函数的指针,然后再次返回。结果应等于原始指针。如果使用转换后的指针来调用其类型与引用的类型不兼容的函数,则该行为是不确定的。
该声明void scriveTitolo2() { … }
定义了一个没有参数类型列表的函数(它使用标识符列表的旧C样式,该列表为空)并且不接受任何参数。一个Callback
指针指向具有参数类型列表,并采取了一个函数const char *
的参数。这些与C 2018 6.7.6.3 15不兼容:
为了使两种功能类型兼容,…如果一种类型具有参数类型列表,而另一种类型由包含(可能为空)标识符列表的功能定义指定,则两种参数的数量必须相同,…
由于它们在参数数量上不一致,因此不兼容。
上面只谈到了从转换void (*)()
为void (*){const char *)
并使用结果调用函数的问题。还有一个单独的问题,就是将函数指针传递给inserisce_cb
,该指针采用类型void *
为实参的指针,该类型是指向对象类型的指针。C标准没有定义将指针转换为函数类型到对象类型的行为。为了解决这个问题,inserisce_cb
应声明为采用指向函数类型的指针,例如void inserisce_cb(Callback c)
。
如果scriveTitolo2
可以更改,则可以通过将其更改为采用const char *
未使用的参数并将其定义更改为来解决兼容性问题void scriveTitolo2(const char *)
。
(请注意,最好scriveTitolo2
使用现代C风格声明as void scriveTitolo2(void) { … }
,而不要使用void
。声明。这与问题无关,因为它不会使函数类型兼容,但是此声明格式为编译器提供了更多信息很多情况下。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句