【问题标题】:Does the size of pointers vary in C? [duplicate]C语言中指针的大小不同吗? [复制]
【发布时间】:2011-04-01 00:11:49
【问题描述】:

可能的重复:
Can the Size of Pointers Vary Depending on what’s Pointed To?
Are there are any platforms where pointers to different types have different sizes?

c 中指向 float 的指针的大小是否可能与指向 int 的指针不同?试过了,各种指针的结果都是一样的。

#include <stdio.h>
#include <stdlib.h>

int main()
{
    printf("sizeof(int*): %i\n", sizeof(int*));
    printf("sizeof(float*): %i\n", sizeof(float*));
    printf("sizeof(void*): %i\n", sizeof(void*));
    return 0;
}

这里的输出(OSX 10.6 64bit)

sizeof(int*): 8
sizeof(float*): 8
sizeof(void*): 8

我可以假设不同类型的指针具有相同的大小(当然在一个拱上)吗?

【问题讨论】:

  • @kotlinski:有两个布尔问题:标题一个(它们是否不同?)和最后一个(它们相同吗?)。你在回答哪一个?
  • @MSalters:哎呀!最后一个......他们可以改变。
  • 1473935 本身就是stackoverflow.com/questions/916051/…的骗子
  • 除了 nearfar,这是程序员在声明指针时赋予的属性,在这里并不真正适用,旧 Crays 的 char* 比其他指针大,因为本机内存方案没有解决字节。

标签: c pointers


【解决方案1】:

指针在同一个拱门上的大小并不总是相同。

您可以阅读更多关于“near”、“far”和“huge”指针的概念,这只是指针大小不同的示例......

http://en.wikipedia.org/wiki/Intel_Memory_Model#Pointer_sizes

【讨论】:

  • 有人可能会说,您所描述的不是“C”。但是既然DOS曾经统治过地球并且是事实上的标准,我给了你一票。
  • 是的,但在这种情况下,类型对大小没有影响?
  • 它可能会有所不同,因为不同的类型可以放在不同的内存段中。
  • @Amigable - 你的意思是“友好”吗?不错的昵称。
  • @Vulcan,名字中没有“Amiga”。还有克拉克盖博,克拉克肯特(几乎),也许还有一个。 :-)
【解决方案2】:

在过去的日子里,使用例如DOS平台上的Borland C编译器,总共有(我认为)5种内存模型,甚至可以在某种程度上混合使用。从本质上讲,您可以选择指向数据的小指针或大指针,以及指向代码的小指针或大指针,以及代码和数据具有(如果我没记错的话)64K 的公共地址空间的“小”模型。

可以在程序中指定“巨大”的指针,而这些指针原本是在“微小”模型中构建的。所以在最坏的情况下在同一个程序中可能有不同大小的指针指向同一个数据类型

我认为标准甚至没有禁止这样做,所以理论上一个不起眼的 C 编译器即使在今天也可以做到这一点。但毫无疑问,有专家能够证实或纠正这一点。

【讨论】:

  • 标准并没有完全禁止它,但特定的细节是非标准的。但是,您正确地指出,您可以独立地在代码和数据的小指针和大指针之间进行选择。
【解决方案3】:

指向数据的指针必须始终与void* 兼容,因此现在通常将它们实现为相同宽度的类型。

这句话不适用于函数指针,它们可能有不同的宽度。因此,在 C99 中,将函数指针转换为 void* 是未定义的行为。

【讨论】:

  • 所有这意味着void * 必须至少是最大的其他指针类型的大小。
  • @caf:您的意思可能是“指向数据类型的其他指针”和“宽度”而不是“大小”,是的,我认为这就是我在第一段中所说的。这不会强制其他指针数据类型具有相同的宽度,但它很有可能,因为从void* 转换回必须仍然具有寻址对象的所有信息。但你是对的,假设的架构可以为所有在 256 字节边界对齐的数据类型保存指针的低位字节;-)
  • 完全正确 - 从void * 转换为double * 可能有损,但反之则不然。
  • 谁能解释一下什么是“宽度”(相对于“尺寸”)?
  • @trinithis,cmets 到一岁的问题不是提问的好地方。宽度是有效用于类型的位数。例如,_Bool 至少有一个 sizeof,因此它至少占用 8 位。但通常它只使用其中的 1 位,因此其宽度仅为 1 而不是 8。其他位则称为填充位。
【解决方案4】:

据我了解,C 标准中没有任何内容可以保证指向不同类型的指针必须具有相同的大小,因此理论上,同一平台上的 int * 和 float * 可以是不同的大小而不会违反任何规则。

要求 char * 和 void * 具有相同的表示和对齐要求,对于不同的指针类型子集还有各种其他类似的要求,但没有什么可以涵盖所有内容。

实际上,除非您进入一些相当晦涩的地方,否则您不太可能遇到使用不同大小指针的任何实现。

【讨论】:

    【解决方案5】:

    是的。这并不常见,但这肯定会发生在不可字节寻址的系统上。例如。具有 64 Kword = 128KB 内存的 16 位系统。在这样的系统上,您仍然可以拥有 16 位 int 指针。但是指向 8 位 char 的 char 指针需要一个额外的位来指示字中的高字节/低字节,因此您将拥有 17/32 位 char 指针。

    这听起来可能很奇怪,但许多 DSP 花费 99.x% 的时间来执行专门的数字代码。如果一个声音 DSP 只需要处理 16 位数据,那么它可能会更简单一些,而将偶尔的 8 位数学运算留给编译器来模拟。

    【讨论】:

      【解决方案6】:

      我打算写一个回复说 C99 有各种指针转换要求,或多或少确保指向数据的指针必须全部相同大小。但是,仔细阅读后,我意识到 C99 是专门设计用于允许针对不同类型的不同大小的指针。

      例如,在整数为 4 字节且必须为 4 字节对齐的架构上,int 指针可能比 char 或 void 指针小两位。如果演员实际上在两个方向上都进行了转换,那么您可以使用 C99。它有助于说明将 char 指针转换为未正确对齐的 int 指针的结果是未定义的。

      请参阅C99 standard。第 6.3.2.3 节

      【讨论】:

      • 完全正确 - 标准不遗余力地允许这样做。
      • 你能提供一个链接到你在哪里读到的吗?
      • thx :)(第 6.3.2.3 节从第 47 页开始,感兴趣的读者可以阅读)
      【解决方案7】:

      是的,指针的大小取决于平台。更具体地说,指针的大小取决于目标处理器架构和编译的“位数”。

      根据经验,在 64 位机器上,指针通常是 64 位,在 32 位机器上通常是 32 位。不过也有例外。

      由于指针只是一个内存地址,因此无论它指向的内存包含什么,它的大小始终相同。所以指向 float、char 或 int 的指针的大小都是一样的。

      【讨论】:

      • Aehm 这不是问题,问题是指向不同类型(float*、int*、void*)的指针是否可以具有不同的大小(在同一平台上),事实并非如此。
      • +1 是的,在古老的 16 位窗口中,根据内存型号和使用情况,有近(16 位)和远指针(32 位)。
      【解决方案8】:

      我可以假设不同类型的指针具有相同的大小(当然在一个拱上)吗?

      对于具有平面内存模型的平台(== 所有流行/现代平台),指针大小将是相同的。

      对于具有分段内存模型的平台,为了提高效率,通常会有不同大小的特定于平台的指针类型。 (例如 DOS 中的 far 指针,因为 8086 CPU 使用分段内存模型。)但这是特定于平台且非标准的。

      您可能应该记住,在 C++ 中,普通指针的大小可能与指向虚拟方法的指针的大小不同。指向虚拟方法的指针必须保留额外的信息,以免与多态性一起正常工作。这可能是我所知道的唯一例外,它仍然是相关的(因为我怀疑分段内存模型是否会恢复)。

      【讨论】:

        【解决方案9】:

        有些平台的函数指针与其他指针的大小不同。

        我从未见过比这更多的变化。所有其他指针最多只能为 sizeof(void*),因为标准要求它们可以转换为 void* 而不会丢失信息。

        【讨论】:

          【解决方案10】:

          指针是一个内存地址 - 因此在特定机器上应该是相同的。 32 位机器 => 4 字节,64 位 => 8 字节。

          因此,无论指针指向的事物的数据类型如何,特定机器上指针的大小都是相同的(因为存储内存地址所需的空间是相同的。)

          假设:我说的是指向数据值的近指针,即您在问题中声明的那种。

          【讨论】:

          • -1,错误。对于初学者,它假定指针指向丢失函数指针的数据(和数据类型)。而 DOS 上的 C 具有 16 位函数指针和 20/32 位数据指针的内存模型。
          • 是的,我忘了在答案中添加“出于所有实际目的”。从技术上讲,答案可能是错误的——C/C++ 总是有例外的规则。但是,从问题中 OP 给出的上下文来看(因为我只是在考虑近(正常)指针),我想它可以回答他。感谢您让我回去阅读!
          猜你喜欢
          • 2020-01-19
          • 2013-06-27
          • 1970-01-01
          • 2023-02-02
          • 1970-01-01
          • 2018-03-12
          • 2013-07-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多