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

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

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

在评估作业期间实际发生了什么?

foo转换类型和;之间有区别 强制转换类型是一个指针并且foo是一个函数。那么,编译器是否将 ' (foo)' 中的内容转换为指向的指针,foo然后才进行强制转换?因为似乎没有其他任何意义;另一种选择是将函数本身转换为指向获取 avoid*并返回inta 的函数的指针,据我所知,函数是内存中一段代码的标签,因此不能成为指针,即一个变量。

4

5 回答 5

5

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

我应该澄清分配复制了函数指针。但是在 C 中,所有函数指针都只是指针。类型和转换都是编译器胶水。

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

于 2009-04-16T18:31:52.077 回答
5

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

话虽如此,通过类型与函数的实际原型不同的指针调用函数(如您的示例所做的那样)是未定义的行为。不要这样做。

附录

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

来自C 标准的第 6.3.2.3 节。

于 2009-04-16T18:32:27.877 回答
2

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

于 2009-04-16T18:32:44.227 回答
2

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

但是请注意,包含这种类型转换的程序的行为在 C 标准中是未定义的。

于 2009-04-16T18:34:03.317 回答
2

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

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

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

2.12.3 指针类型

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

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

于 2009-04-16T19:35:23.623 回答