函数指针的大小有啥保证?

Posted

技术标签:

【中文标题】函数指针的大小有啥保证?【英文标题】:What is guaranteed about the size of a function pointer?函数指针的大小有什么保证? 【发布时间】:2011-04-25 21:39:12 【问题描述】:

在 C 中,我需要知道结构的大小,其中包含函数指针。我可以保证在所有平台和架构上:

void* 的大小与函数指针的大小相同? 函数指针的大小不会因其返回类型而有所不同? 函数指针的大小不会因其参数类型而有所不同?

我认为所有这些的答案都是肯定的,但我想确定一下。就上下文而言,我打电话给sizeof(struct mystruct),仅此而已。

【问题讨论】:

【参考方案1】:

来自 C99 规范,第 6.2.5 节,第 27 段:

指向 void 的指针应具有相同的 表示和对齐 需求作为一个指针 字符类型。同样,指针 到合格或不合格的版本 兼容类型应具有相同的 表示和对齐 要求。所有指向的指针 结构类型应具有相同的 表示和对齐 互相要求。全部 指向联合类型的指针应具有 相同的表示和对齐 互相要求。指针 其他类型不必有相同的 表示或对齐 要求。

所以不;不保证void * 可以保存函数指针。

以及第 6.3.2.3 节第 8 段:

指向一种类型的函数的指针 可以转换为指向 a 的指针 另一种类型的功能并返回 再次;结果应比较相等 到原来的指针。

暗示一种函数指针类型可以保存任何其他函数指针值。从技术上讲,这与保证函数指针类型不能改变大小不同,只是保证它们的值彼此占据相同的范围。

【讨论】:

【参考方案2】:

不,不,不。

C 不支持具有不同代码和数据指针大小的哈佛架构,因为理想情况下,在为此类架构编程时,您希望将数据存储在程序内存中(字符串文字等),并且您需要这样做对象指针指向代码空间。但它并没有禁止它们,所以就标准而言,函数指针可以引用与数据地址空间大小不同的地址空间。

但是,任何函数指针都可以转换为另一个函数指针类型[*]并返回而不会丢弃值,就像任何对象指针都可以转换为void*并返回一样。因此,函数指针的大小会根据其签名而变化,这将是相当令人惊讶的。如果您必须能够以某种方式在更小的空间中存储相同的值,然后在回退时检索它,那么额外的空间没有明显的“用途”。

[*] 谢谢,肖特。

【讨论】:

更一般地说:任何函数指针都可以转换为任何其他函数指针类型并返回。 (C99 6.3.2.3/8) @schot:对,在那种情况下,让它们不同大小确实是不正当的,因为无论大小如何,所有函数指针类型都必须表示完全相同的一组值。即每个函数的地址,加上一个空指针。 优秀的答案。我前几天的问题在这里说明了潜在的陷阱:***.com/questions/3889541/… "C 并不真正支持哈佛架构";我认为这是一个红鲱鱼。有很多这样的架构支持 C! @Oli:当然,您可以将内容复制到数据空间中,但是您有(a)但没有(b)。您正在占用宝贵的内存,这正是程序员控制优化的动机。通过“丑陋的黑客”,我想到了nongnu.org/avr-libc/user-manual/pgmspace.html。然后你不能得到一个真正的“对象”指针,例如程序本身可以传递给memcpy,因为 memcpy 不知道如何取消引用它。要做到这一点,你必须投降,只是增加对象指针的大小,再次消耗宝贵的内存,并且可能需要在每次内存访问时进行运行时切换!【参考方案3】:

除了其他答案,***这样说:

http://en.wikipedia.org/wiki/Function_pointer

虽然 C 中的函数指针和 C++ 可以很简单地实现 地址,所以通常 sizeof(Fx)==sizeof(void *),会员 C++中的指针经常被实现 作为“胖指针”,通常是两个或 一个简单的大小的三倍 函数指针,为了处理 使用虚拟继承。

函数指针是一种抽象。只要满足标准的要求,一切皆有可能。 IE。如果您的程序中的函数少于 256 个,则函数指针可以通过使用单个字节来实现,其值为 0 表示 NULL,值 1 到 255 作为具有物理地址的表的索引。如果超过 255 个函数,可以扩展为使用 2 个字节。

【讨论】:

我不明白这是怎么回事。对于合法的 C 实现来说,这确实是一种可能性,但如果有这样的实现,我会感到惊讶。 不是我的反对意见,但是 C++ 成员指针的东西是无关紧要的,因为问题是关于 C 的。最后一段是一个非常好的观点,不过,函数指针当然 可以 合法地成为某个表的索引,具有额外的间接级别来实际调用它们。【参考方案4】:

有一个过去很常见的不同尺寸的实际示例。在 MS-DOS 和早期的 Windows C 编程中,在“中等”内存模型中,您有 16 位数据指针和 32 位函数指针,而“紧凑”内存模型则相反。

【讨论】:

以上是关于函数指针的大小有啥保证?的主要内容,如果未能解决你的问题,请参考以下文章

为啥free函数不在释放内存后,将指针置NULL,野指针有啥用

将指针传递给保证归零的内存

如果基类指针不能访问派生类成员函数,那么多态有啥方便呢?

strlen()函数和sizeof算符

将字符串与指向字符串的指针作为参数传递给函数时,时间复杂度有啥区别?

如何确定我平台上的最大指针大小?