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

时间:2014-06-18 22:51:33

标签: c pointers sizeof

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

让我感到惊讶的一件事是,指针的大小可能会根据它指向的数据类型而有所不同。我原以为,在32位架构上,所有指针的大小都是4字节,但事实证明,函数指针的大小可能不同(即:大于我预期的大小)。为什么这是C编程语言?我找到了一篇文章,为C ++解释了这一点,以及如何the program may have to cope with virtual functions,但这似乎并不适用于纯C.此外,似乎使用"远"和"附近"指针不再是必需的,所以我不会看到那些进入等式的人。

因此,在C中,理由,标准或文档描述了为什么并非所有指针在同一架构上的大小相同?

谢谢!

5 个答案:

答案 0 :(得分:6)

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

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

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

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

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

答案 1 :(得分:3)

  

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

C11:6.2.5 p(28):

  

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

6.3.2.3指针p(8):

  

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

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

答案 2 :(得分:2)

还有一点:

问:那么,可以肯定地说,虽然在定义指针时我不必明确使用far / near关键字,但这是自动处理的#34;#34;由编译器?

  

答: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位宽,操作   系统隐藏了你的片段。

答案 3 :(得分:1)

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

CODE:

#include <stdio.h>

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

答案 4 :(得分:1)

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

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

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