【问题标题】:C why would a pointer be larger than an integerC为什么指针会大于整数
【发布时间】:2012-03-11 02:26:43
【问题描述】:

我现在正在一台 linux 机器上使用 GCC 中的 sizeof(),我发现了一些非常令人惊讶的东西。

printf ("\nsize of int = %lu\n", sizeof(int));
printf ("\nsize of int* = %lu\n", sizeof(int *));

产量

size of int = 4
size of int* = 8

我认为指向整数的指针的大小会比实际的整数本身小得多!

我现在正在研究嵌入式软件,我的理解是通过引用传递比通过值传递更有效(就功率而言)。

如果指针的大小大于实际值,请有人澄清为什么通过引用传递比通过值传递更有效

谢谢!

【问题讨论】:

  • 您是否在 64 位操作系统上运行?
  • 不要比较对象(或类型)的大小。根据需要使用它们。
  • 太棒了!我在 64 位机器上,但为什么按引用传递比按值传递更有效?
  • 它不一定是“低效”的,因为参数恰好是 64 位而不是 32 位。就“功耗”而言,您需要计算 1) 执行操作所需的 #/指令,以及 2) 完成指令所需的 #/cycles。 “通过引用传递”可以消除复制数据的需要。这可以为数据记录节省大量资金。对于像“int”这样的标量值,它可能比“按值传递”效率略低。
  • 谢谢 paulsm4,这正是我想要的。

标签: c memory embedded


【解决方案1】:

整数可以是编译器编写者喜欢的任何大小,唯一的规则(在标准 C 中)是:a)int 不小于 short 或大于 long,并且 b)int 至少16 位。

在 64 位平台上将 int 保持为 32 位以实现兼容性并不少见。

【讨论】:

  • 如果不明显的话,“你”是指实现 C 的人。
  • @JerryCoffin - 抱歉,我将该号码扫描为 32 位。我确信它在早期的 Windows 上曾经是 16 位 - 当然是。
  • @Jerry:另一种确保至少 32 位的方法是使用int_least32_t。它是 C99 中的必需类型,与 long 不同,您不应该在 LP64 实现中使用不必要的大 64 位类型。缺点是您不想在程序中多次输入int_least32_t,因此您最终需要对它进行类型定义并为读者引入额外的间接级别。
【解决方案2】:

指向整数的指针可以指向单个整数,但同一个指针也可以指向十个、二十个、一亿或一百万个整数。

显然,传递单个 8 字节指针代替单个 4 字节整数并不是胜利;但是传递一个 8 字节指针代替一百万个 4 字节整数肯定是。

【讨论】:

    【解决方案3】:

    通过引用传递效率更高,因为不需要复制任何数据(除了指针)。这意味着只有在传递具有许多字段或结构的类或任何其他大于所用系统上的指针的数据时,这才更有效。

    在您提到的情况下,不使用指针确实可能更有效,因为实际值小于指向它的指针(至少在您使用的机器上)。 请记住,在 32 位机器上,指针有 4 个字节(4*8 = 32 位),而在 64 位机器上,您显然使用的指针有 8 个字节(8*8 = 64 位)。

    在更旧的 16 位机器上,指针确实只需要 2 个字节,也许有一些嵌入式系统仍在使用这种架构,但我不知道这个......

    【讨论】:

      【解决方案4】:

      一件事与另一件事无关。一个是地址,指向某物的指针,不管它是 char、short、int 还是结构。另一个是一种特定于语言的东西,称为 int,该系统的编译器和该版本的编译器以及命令行选项可能恰好定义为某种大小。

      看起来好像您在 64 位系统上运行,所以您的所有指针/地址都将是 64 位。他们指出的是一个单独的讨论,长可能也将是 64 位,有时整数,短裤可能仍然是 16 位,但不是硬/快速规则,而字符希望是 8 位,但也不是硬/快速规则。

      在使用 llvm-gcc 时交叉编译可能会变得更糟,而在 clang 像现在这样可靠之前。对于 64 位主机,字节码都是基于 64 位主机生成的,所以 64 位整数、64 位指针等。然后当你为 arm 目标做后端时,它必须使用编译器库调用来完成所有这些64位工作。变量几乎不需要短得多的整数,而是整数。 -m32 开关坏了,由于主机不是最终目标,您仍然得到 64 位整数。 gcc直接好像没有这个问题,clang+llvm目前也没有这个问题。

      简短的回答是语言定义了一些数据类型 char、short、int、long 等,这些数据类型具有编译器实现定义的大小。地址只是另一种实现定义的数据类型。这就像问为什么短的字节数与长的字节数不同?因为它们是不同的数据类型,一种是短的,一种是长的。一个是地址,另一个是变量,两种不同的东西。

      【讨论】:

        【解决方案5】:

        当要传递的值大于引用的大小时,按引用传递比按值传递更有效。如果你传递的是一个大的结构/对象,那么通过引用传递是很有意义的。如果您想对您的值进行持久修改,传递引用也是有意义的。

        【讨论】:

          【解决方案6】:

          指针必须能够引用所有内存。如果(虚拟)内存大于 4 Gi 字节左右,则指针必须大于 32 位。

          【讨论】:

            【解决方案7】:

            http://developers.sun.com/solaris/articles/ILP32toLP64Issues.html

            将 32 位程序转换为 64 位程序时,只有 long 类型 指针类型的大小从 32 位变为 64 位;的整数 类型 int 保持 32 位大小。

            在 64 位可执行文件中,指针是 64 位的。长整数也是 64 位,但整数只有 32 位。

            在 32 位可执行文件中,指针、整数和长整数都是 32 位的。 32 位可执行文件还支持 64 位“long long”整数。

            【讨论】:

            • 并非普遍正确,可能在一个编译器或该编译器的一代(例如 gcc 4.x)的一个实例中。
            • 正如 dwelch 所指出的,不同的编译器使用不同的内存模型。 Microsoft 使用 IL32P64(32 位 long 和 64 位指针),大多数 Unices(显然包括 Mac OS X)使用 I32LP64(64 位 long 和 64 位指针)。我不确定 GCC for Windows。
            【解决方案8】:

            在 C 中,指针,任何指针,都只是一个内存地址。您在 64 位机器上,在硬件级别,内存地址使用 64 位值引用。这就是为什么 64 位机器可以使用比 32 位机器更多的内存。

            【讨论】:

            • 某个 CPU 的 nn-bits 代表它可以在一条指令中处理多大的数据块,也称为“数据总线”。这与计算机上有多大的地址无关。事实上,地址总线的宽度通常与数据总线不同。在 32/64 位(数据总线)PC 计算机上,为方便起见,地址总线恰好与数据总线一样大。
            猜你喜欢
            • 1970-01-01
            • 2016-01-22
            • 2022-07-16
            • 2015-01-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-25
            相关资源
            最近更新 更多