如何在C中实现转换函数?

时间:2009-04-16 18:27:24

标签: c pointers function casting function-pointers

int foo(char *c)  {...}

main() {
     int (*thud)(void *);

     thud = (int (*)(void *))(foo);
}

评估作业时实际发生了什么?

演员类型与foo之间存在差异;演员类型是指针foo函数。那么,编译器是否将“(foo)”中的内容转换为指向foo的指针,然后才进行转换?因为没有别的东西似乎有意义;另一个选项是函数本身被转换为指向 void* 并返回int <的函数的指针/ em>,据我所知,函数是内存中一段代码的标签,因此不能成为指针,这是一个变量。

5 个答案:

答案 0 :(得分:5)

在C中,绝对没有。它只是编译胶水,以防止你做一些愚蠢的事情。在C中,调用者负责维护堆栈帧,因此在调用函数时需要强制转换(即参数和返回值被压入堆栈)。这使得它安全(r),因为调用者的堆栈不可能不正确地变异。但是,在某些极少数情况下,调用的函数仍然可能会扰乱调用者的堆栈。

我应该澄清一下,赋值复制了函数指针。但在C语言中,所有函数指针都只是指针。类型和转换都是编译器粘合剂。

另一个澄清:标准指定(在6.5.2.2中)如果调用者使用不兼容的类型,则行为是未定义的。例如,将一个返回void的函数转换为一个返回int然后调用该函数的函数,“返回”值是没有意义的。在调用函数之前将函数转换为兼容类型是个好主意,否则您可能会看到意外的结果。

答案 1 :(得分:5)

当使用时,函数的名称是指针。它有点类似于数组名称是指向其第一个元素的指针。

话虽这么说,通过一个与函数的实际原型不同的类型的指针调用一个函数(如你的例子那样)是未定义的行为。不要这样做。

附录

  

如果转换的指针用于调用类型与指向类型不兼容的函数,则行为未定义。

来自C标准的section 6.3.2.3

答案 2 :(得分:2)

C中的指针是地址,即存储在某个地方的数字。 C中的函数是某些代码的地址。这两个是同一个。

答案 3 :(得分:2)

正确的术语是衰变。函数foo在转换之前衰减到指向foo的指针。演员本身将是我能想到的所有平台上的无操作。

但请注意,C标准未定义包含此类强制转换的程序的行为。

答案 4 :(得分:2)

这将是对Rick C. Petty的答案的评论 - 但它不适合300个字符。

C标准不是很严格 - 指向对象(和函数不是对象)的指针可以转换为“指向void的指针”并且可以毫无问题地返回。 POSIX要求指向函数的指针大小相同,并且可以转换为指向void的指针。

POSIX 2008 - 一般信息 - 编译环境

2.12.3指针类型

  

所有函数指针类型应与void指向的类型指针具有相同的表示形式。将函数指针转换为void *不得改变表示。这种转换产生的void *值可以使用显式转换转换回原始函数指针类型,而不会丢失信息。

     

注意:   ISO C标准不要求这样,但它是POSIX一致性所必需的。