【问题标题】:Equivalent of uintptr_t/intptr_t for pointers to functions?uintptr_t/intptr_t 等价于指向函数的指针?
【发布时间】:2023-11-27 01:36:01
【问题描述】:

Afaik uintptr_tintptr_t 可用于保存任何指向 void 的指针。因此,这些类型可用于存储指向数据的指针。

在 C99 或更高版本中,是否有类似的有符号和无符号整数类型能够保存指向函数的指针?

【问题讨论】:

  • 没有单一的“函数指针”类型(每种类型取决于函数原型)。
  • 您甚至无法将函数指针转换为void *。 C和C++也是不同的语言。请将您的问题限制在其中之一。
  • @barakmanos 是的,但是每个指向函数的类型在转换后都可以存储任何其他指向函数的类型,所以如果你有一个足够大的整数类型来存储一个指向函数的类型,你应该有一个足够大的整数类型。
  • @Olaf 您可以将其转换为足够大的整数类型。只是不能保证任何整数类型都足够大。
  • @hvd:是的,我自己找到的。我真的很确定他们在那里也使用了术语“对象指针”。对困惑感到抱歉。我删除了我的 cmets。

标签: c language-lawyer c99 c11


【解决方案1】:

不,没有这样的类型。

函数指针只能可靠地转换为其他函数指针类型(然后,只有在指向正确的函数类型时才被取消引用)。

6.3.2.3/6 涵盖了 C 中函数指针到整数的转换:

任何指针类型都可以转换为整数类型。除非前面指定,结果是实现定义的。如果结果不能以整数类型表示,则行为未定义。结果不必在任何整数类型的值范围内。

请注意,即使整数类型足够大,也不能保证强制转换为整数并返回到函数指针。

在 C++ 中,文本位于 [expr.reinterpret.cast] 点 4 和 6。行为类似,但它明确保证如果存在足够大小的整数,则将函数指针转换为整数并再次返回检索原始函数指针。

【讨论】:

  • 只是补充一点,实现必须指定实现定义行为。因此,人们应该能够找到这种转换是否以及如何对特定实现有效。这可以由 ABI 完成,不一定在编译器中完成。 void * 和函数指针之间可能会进行类似的转换(参见 J.5.7)。
  • 只是为了通知其他读者:C 标准中的 J.5 是关于可移植性问题的信息性(非规范性)附件 J 中关于 C 语言常见扩展的部分.
  • 您可以使转换可靠:_Static_assert(sizeof(uintptr_t) >= sizeof(func_pointer_t), "bleh");。然后这种转换只会在指针与地址不同的晦涩系统上失败(IMO 这样的系统无论如何都应该崩溃。)
  • @Lundin:仅仅因为函数指针和其他指针的大小不同并不意味着指针是“不同于地址的东西”。不是每台机器都是冯诺依曼的(事实上,由于嵌入式 CPU 的数量远远超过桌面 CPU并且因为 x86 在技术上不是冯诺依曼启动的 [它是混合的],我认为 大多数 系统不是冯诺依曼)。在嵌入式中,函数指针通常比其他指针大(也就是说,它们经常 --- 但并不总是 --- 在 C 中无论如何都填充到相同的类型)。
  • @TimČas 标准甚至明确表示地址是指针。 (C11 6.5.3.2/3)。我猜“指针不是地址”人群实际上是指“指针不是整数”,这在某种程度上具有讽刺意味。