是否有任何平台指向不同类型的指针有不同的大小?

时间:2009-05-27 14:35:03

标签: c pointers sizeof

C标准允许指向不同类型的指针具有不同的大小,例如允许sizeof(char*) != sizeof(int*)。但是,它确实要求如果指针转换为void*然后转换回其原始类型,则必须将其与原始值进行比较。因此,逻辑上遵循所有类型sizeof(void*) >= sizeof(T*)的{​​{1}},对吗?

在当今使用的大多数常见平台上(x86,PPC,ARM和64位变体等),所有指针的大小等于本机寄存器大小(4或8字节),无论指向何处类型。是否存在任何深奥或嵌入式平台,其中指向不同类型的指针可能具有不同的大小?我特别询问数据指针,虽然我也有兴趣知道是否存在 function 指针具有异常大小的平台。

我肯定询问C ++的指向成员的指针和指向成员函数的指针。这些在常见平台上占用不同的大小,甚至可以在一个平台内变化,具体取决于指针类的属性(非多态,单继承,多继承,虚继承或不完整类型)。

7 个答案:

答案 0 :(得分:45)

Answer from the C FAQ

  

Prime 50系列使用了段07777,空指针的偏移量为0,至少对于PL / I。后来的模型使用了段0,偏移0用于C中的空指针,需要新的指令,如TCNP(测试C空指针),显然是对所有现存的写得不好的C代码的一个改进做出了错误的假设。较旧的,字寻址的Prime机器也因为需要比字指针(int *)更大的字节指针(char *)而臭名昭着。

     

Data General的Eclipse MV系列有三种架构支持的指针格式(字,字和位指针),其中两个由C编译器使用:char *和void *的字节指针,以及其他所有字的指针。由于历史原因在从16位Nova线演变32位MV线期间,字指针和字节指针在字中的不同位置具有偏移,间接和环保护位。将不匹配的指针格式传递给函数会导致保护错误。最终,MV C编译器添加了许多兼容性选项,以尝试处理具有指针类型不匹配错误的代码。

     

一些霍尼韦尔 - 布尔大型机使用位模式06000作为(内部)空指针。

     

CDC Cyber​​ 180系列具有48位指针,包括环,段和偏移。大多数用户(在环11中)具有0xB00000000000的空指针。旧的CDC补充机器通常使用全1位字作为各种数据的特殊标志,包括无效地址。

     

旧的HP 3000系列使用不同的字节地址寻址方案而不是字地址;就像它上面的几台机器一样,它使用char *和void *指针的不同表示而不是其他指针。

     

Symbolics Lisp Machine是一种标记架构,甚至没有传统的数字指针;它使用该对(基本上是一个不存在的句柄)作为C空指针。

     

取决于所使用的“内存模型”,8086系列处理器(PC   兼容性)可以使用16位数据指针和32位函数   指针,反之亦然。

     

一些64位Cray机器在a的低48位表示int *   字; char *另外使用高16位中的一些来表示a   一个字内的字节地址。

     

其他链接:包含更多详情的message from Chris Torek   关于其中一些机器。

答案 1 :(得分:28)

不是你要问的问题,但是在16位DOS / Windows时代,你确实区分了指针和远指针,后者是32位。

我可能有错误的语法...

int *pInt = malloc(sizeof(int));
int far *fpInt = _fmalloc(sizeof(int));

printf("pInt: %d, fpInt: %d\n", sizeof(pInt), sizeof(fpInt));

输出:

pInt:2,fpInt 4

答案 2 :(得分:13)

因此,逻辑上遵循所有类型T的sizeof(void*) >= sizeof(T*),对吗?

不一定如此,因为sizeof是关于存储表示的,并且并非所有位模式都必须是有效值。我认为你可以编写一个符合sizeof(int*) == 8sizeof(void*) == 4的符合实现,但int *的可能值不超过2 ^ 32。不确定你为什么要这样做。

答案 3 :(得分:11)

回到DOS,8088和分段存储器的黄金岁月,通常指定一个“存储器模型”,其中例如所有代码都适合64k(一个段)但数据可以跨越多个段;这意味着函数指针将是2个字节,一个数据指针,4个字节。不确定是否仍然有人为这种机器编程,也许有些机器仍然可以在嵌入式应用中存活。

答案 4 :(得分:7)

人们很容易想象哈佛架构机器具有不同大小的功能指针和所有其他指针。不知道一个例子......

答案 5 :(得分:7)

在带有分页闪存或RAM的某些嵌入式微控制器上仍然使用近端指针和远指针,以允许您指向同一页面(指针附近)或其他页面(远指针,因为它包含页面而更大)信息)。

例如,飞思卡尔的HCS12微控制器采用16位冯·诺依曼架构,这意味着没有地址可以超过16位。由于这会限制可用的代码空间量,因此存在一个8位页面寄存器。

因此,要指向同一代码页中的数据,只需指定16位地址;这是近指针。

要指向另一个代码页中的数据,您必须在该页面中包含8位页码和16位地址,从而产生一个24位远指针。

答案 6 :(得分:6)

例如,指向数据的指针的大小可能与指向函数的指针不同。这种情况在嵌入式系统的微处理器中很常见。像dmckee提到的哈佛架构机器让这很容易发生。

事实证明,它使gcc后端成为一种痛苦! :)

编辑:我不能详细介绍我正在谈论的具体机器,但让我补充一下为什么哈佛机器能够轻松实现这一目标。哈佛架构具有不同的存储和通向指令和数据的路径,因此如果指令的总线比数据的总线“大”,则必然会有一个函数指针,其大小大于指向数据的指针! / p>