【问题标题】:Storing the pointer to a function pointer in a void*将指向函数指针的指针存储在 void* 中
【发布时间】:2015-05-20 13:20:03
【问题描述】:

我明白你为什么不能这样做:

void(*fp)(void) = &function;
function_taking_void_pointer((void*)fp);

因为类型的长度可能不同。

但是添加另一层间接有什么问题:

void(*fp)(void) = &function;
void(**fpp)(void) = &fp;
function_taking_void_pointer((void*)fpp)

我的想法是:指向函数指针的指针应该指向数据内存,因此应该与 void* 类型具有相同的长度。

那我到底错在哪里?

【问题讨论】:

  • 上帝帮助那些在你完成后必须阅读这段代码的人......
  • 当然 void 指针是为这些类型的“黑客”制作的。但我想它绝对没有好的设计将函数指针传递给一个函数,该函数可能是为了处理不同的数据类型,如 int*、float*、double*、struct 不管*等。所以我认为你最好写一个参数是指向函数的指针的函数。
  • 好吧,那么别提这些奇怪的东西了。
  • 请记住,函数指针可以存储在任何其他函数指针中(通过强制转换),只要它在用于进行函数调用之前转换回正确的函数指针类型。所以你可以使用void (*)(void)(或任何函数指针类型)作为函数指针的一种“void*”。
  • 此外,由于 dlsym() 函数的指定方式,POSIX 排序要求函数指针可以通过 void* 往返。

标签: c pointers function-pointers


【解决方案1】:

你说得对,所有指针类型都是对象类型

N1570 6.3.5 类型,第 20 段,第五个列表项:

  • 指针类型可以派生自函数类型或对象类型,称为 引用类型。指针类型描述其值提供引用的对象 到被引用类型的实体。从引用类型 T 派生的指针类型 有时称为“指向 T 的指针”。从一个指针类型的构造 引用类型称为“指针类型派生”。 指针类型是完整的 对象类型。

但指向对象类型的指针不一定具有与void* (6.2.5 p28) 相同的大小。

  1. 指向 void 的指针应具有与 指向字符类型的指针。48) 同样,指向合格或不合格版本的指针 兼容类型应具有相同的表示和对齐要求。全部 指向结构类型的指针应具有相同的表示和对齐要求 作为彼此。所有指向联合类型的指针都应具有相同的表示形式和 对齐要求彼此。 指向其他类型的指针不必相同 表示或对齐要求。

但是,它们都可以转换void* (6.3.2.3 p1):

  1. 指向 void 的指针可以转换为指向任何对象类型的指针或从指向任何对象类型的指针转​​换。指向的指针 任何对象类型都可以转换为指向 void 并再次返回的指针;结果应 比较等于原始指针。

【讨论】:

  • 标准没有说明将函数指针类型转换为void *;您明确引用了它所说的话:指向 void 的指针可以转换为或从 指向任何对象类型的指针函数不是对象;这就是为什么它说指针类型可以派生自函数类型对象类型;这两组类型(指向对象的指针和指向函数的指针)不相同,并且不一定可转换。 POSIX 甚至删除了用于提供退出条款的文本。有些机器的函数指针非常精细(大、复杂)。
  • @JonathanLeffler 是的,这就是我的回答。请记住关于指向函数指针的指针 的问题。那是对象类型,可以转换为void*
【解决方案2】:

这段代码sn-p是错误的。

void(*fp)(void) = &function; function_take_void_pointer((void*)fp);

在 C/C++ 中,function name 将被重新定位到linking stage 中的特定地址,因此您不能在function name 之前使用&。另外function name在C/C++中不是变量,所以你也不能尝试获取它的地址。

【讨论】:

  • 如果foo()是一个函数,你可以使用&foo。这与使用foo 本身相同。
  • 与静态分配的数组相同。您可以包含&,也可以省略&。编译器会以同样的方式解释它。
猜你喜欢
  • 2021-06-03
  • 1970-01-01
  • 2019-02-03
  • 1970-01-01
  • 2018-04-19
  • 1970-01-01
  • 2021-07-22
  • 1970-01-01
  • 2013-07-19
相关资源
最近更新 更多