sizeof指针在同一架构上的数据类型不同

我一直在阅读一些post,并注意到指针根据sizeof可以是不同的大小,具体取决于代码编译和运行的体系结构。 对我来说似乎足够合理(即:32位架构上的4字节指针,64位上的8字节,完全有意义)。

让我感到惊讶的一件事是,指针的大小可以根据它指向的数据类型而有所不同。 我原以为,在32位架构上,所有指针的大小都是4个字节,但事实certificate,函数指针的大小可能不同(即:大于我预期的大小)。 为什么这是C编程语言? 我找到了一篇文章解释了这个C ++,以及程序如何处理虚函数 ,但这似乎不适用于纯C.此外,似乎使用“远”和“近”指针是不再需要,所以我没有看到那些进入等式的人。

那么,在C中,什么理由,标准或文档描述了为什么不是所有指针在同一架构上都是相同的大小?

谢谢!

C标准规定了所要求的法律:

  • 所有数据指针都可以转换为void*并返回而不会丢失信息。
  • 所有struct -pointers都具有相同的表示+对齐,因此可以相互转换。
  • 所有union指针都具有相同的表示+对齐,因此可以相互转换。
  • 所有字符指针和void指针都具有相同的表示+对齐。
  • 所有指向限定和非限定兼容类型的指针都应具有相同的表示+对齐。 (例如,相同类型的未签名/签名版本兼容)

  • 所有函数指针都具有相同的表示+对齐,并且可以转换为任何其他函数指针类型并再次返回。

不需要更多。
委员会通过检查所有当前的实施和机器并尽可能多地编纂保证来达到这些保证。

在指针自然是单词指针而不是字符指针的架构上,您可以获得不同大小的数据指针。
在具有不同大小的代码/数据空间(许多微处理器)的架构上,或者需要额外信息来正确调用函数(如itanium,尽管它们经常隐藏在数据指针后面),您可以获得不同大小的代码指针数据指针。

那么,在C中,什么理由,标准或文档描述了为什么不是所有指针在同一架构上都是相同的大小?

C11:6.2.5 p(28):

指向void的指针应具有与指向字符类型的指针相同的表示和对齐要求。 类似地,指向兼容类型的合格或不合格版本的指针应具有相同的表示和对齐要求。 所有指向结构类型的指针都应具有相同的表示和对齐要求。 所有指向union类型的指针都应具有相同的表示和对齐要求。 指向其他类型的指针不需要具有相同的表示或对齐要求

6.3.2.3指针p(8):

指向一种类型的函数的指针可以被转换为指向另一种类型的函数的指针并且再次返回; 结果应该等于原始指针。 如果转换的指针用于调用类型与指向类型不兼容的函数,则行为未定义

这澄清了指向数据的指针和指向函数的指针的大小不同。

还有一点:

问:那么,可以肯定地说,虽然我在定义指针时不必显式使用far / near关键字,但编译器会“自动”处理这个问题吗?

答: http : //www.unix.com/programming/45002-far-pointer.html

这是来自8086等分段架构的历史时代错误。

在昔日的时代,有8080,这是一个8位处理器,16位地址总线,因此16位指针。

随着8086的推出,为了支持某种程度的向后兼容性,它采用了分段架构,可以根据星期几使用16位,20位或32位指针。 指针是16位段寄存器和16位近偏移的组合。 这导致了微小的,小的,中的,大的和巨大的内存模型的兴起,具有近,远和巨大的指针。

其他架构(如68000)没有采用这种方案,而是采用了所谓的平面存储器模型。

使用80386和真正的32位模式,所有指针都是32位,但具有讽刺意味的是现在非常靠近指针但是32位宽,操作系统会隐藏你的段。

我在三个不同的平台上编译了这个; 在每种情况下,char *指针都与函数指针相同:

码:

 #include  int main (int argc, char *argv[]) { char * cptr = NULL; void (*fnptr)() = NULL; printf ("sizeof cptr=%ld, sizeof fnptr=%ld\n", sizeof (cptr), sizeof (fnptr)); return 0; } 

结果:

  char ptr fn ptr -------- ------ Win8/MSVS 2013 4 4 Debian7/i686/GCC 4 4 Centos/amd64/GCC 8 8 

一些架构支持多种地址空间。 虽然标准中没有任何内容要求实现提供对底层平台支持的所有地址空间的访问,实际上标准没有提供关于如何提供这种支持的指导,但是支持多个地址空间的能力可能使得程序员知道他们编写的代码比其他方式更好。

在某些平台上,一个地址空间将包含所有其他地址空间,但访问该地址空间中的内容将比访问已知在其特定部分中的内容更慢(有时是2倍或更多)。 在其他平台上,不会有任何“主”地址空间,因此需要不同类型的指针来访问不同空间中的内容。

我不同意多个地址空间的存在应被视为遗物的说法。 在许多ARM处理器上,一个程序有可能拥有高达1K-4K(取决于确切的芯片)的全局变量,它可以被访问两倍 – 并且代码少于 – “正常”全局变量。 我不知道任何可以利用它的ARM编译器,但是没有理由ARM的编译器不能这样做。