【问题标题】:sizeof(): the size of a class isn't the same as the size of it's members together?sizeof():一个类的大小与其成员的大小不一样?
【发布时间】:2011-04-23 06:35:00
【问题描述】:

首先,在我的系统上保持以下状态:sizeof(char) == 1sizeof(char*) == 4。 很简单,当我们在下面计算类的总大小时:

class SampleClass { char c; char* c_ptr; };

我们可以说sizeof(SampleClass) = 5。但是,当我们编译代码时,我们很容易看到sizeof(SampleClass) = 8

所以问题是“计算的问题在哪里?” :S

  • 语言:C++
  • 编译器:gcc 4.4.0
  • 操作系统:Tinycore

【问题讨论】:

  • “每个人都知道一个 char 占用 1 个字节,而一个指针占用 4 个字节” 人们不知道这一点,因为它不是真的,除非在一组选定的架构上。近年来非常常见的场景,但是对于所谓的“事实”中的任何一个都没有根本性。请注意,sizeof(char) 1,但 not 是否意味着一个字符是 8 位。
  • 绝对你是对的,但由于我在问题的最后一行定义,它仅限于我拥有的环境(32 位拱门,32 位操作系统)。无论如何,谢谢你的警告。
  • 即使说您使用的是 32 位机器也不能证明这些陈述中的任何一个都是正确的。您习惯使用的机器是 32 位字,但具有 8 位字节寻址能力。可能存在只能寻址 32 位块的 32 位字的机器,在这种情况下,原始字符 必须 为 32 位,sizeof(void *) 很可能是 1(现在是时候了实现压缩字符类型以避免在每个 char 上浪费 24 位)。要做出这样的声明,您必须命名架构和编译器(包括版本)。
  • 仅供参考,操作系统:tinycore 3 编译器:gcc4.4.0 架构:atom x86
  • @dmckee:这样的环境不会是 linux(至少,不是我们所知道的 linux。也许是受 linux 启发的东西)。 POSIX 要求 CHAR_BIT 完全是 8。当然,通过仿真,您可以在该硬件之上的某个地方运行 linux,或者您可以在 linux 之上的某个地方提供该环境,但在任何一种情况下,当谈到 32 -bit-char 环境将其描述为“32 位 linux”是错误的。提问者说“32位linux”,这足以告诉我们charchar*的大小。

标签: c++ char sizeof pointers


【解决方案1】:

这是由填充引起的。
编译器正在添加填充:

  • 尽可能快地访问成员
  • 还可以制作对象包的数组,以便高效访问元素。

因此,大小为 1 的对象可以对齐到 1 字节边界,并且仍然易于/高效地读取。虽然大小为 4 的对象需要在 4 字节边界上对齐(根据您的编译器而定(从技术上讲,您可以对齐到 1 字节边界,但这意味着您通常需要多条指令来提取和组合,因此写入 4 字节边界更有效))。

因此,为了结构的最佳对齐,最好按大小对成员进行排序(最大在前),这将为您在大多数正常情况下提供最佳打包策略。

不过,这不会阻止您的对象为 8 个字节。
由于编译器还考虑到您的类可以在数组中使用。因此,数组中的每个元素都需要对齐,以便每个元素的最大成员正确对齐。

【讨论】:

    【解决方案2】:

    编译器通常会在结构中添加填充以在字边界上对齐它们(因为访问字对齐的位置需要更少的内存访问,因此速度更快)。

    因此,即使char 仅占用 1 个字节,c_ptr 也会移动到下一个 4 字节边界,因此结果为 8 个字节。

    【讨论】:

    • 现在说得通了,但是当只有char 退出时,为什么它只需要1 个字节?如果访问速度更快,为什么编译器不将其占用最多 4 个字节?
    • 并不是访问 4 个字节更快,只是访问 4 个字节的倍数的内存位置(在 32 位系统上)更快。当只有 1 个字符时,大小为 1,但 1 个字符仍将在 4 字节边界上对齐。
    • 知道了,谢谢 :) 但是当编译器功能关闭时,说类的 sizeof 是 5 而不是 8 并没有错,对吧?
    • 是的,事实上,有一个指令可以做到这一点:#pragma pack
    • @casablanca:对象的对齐要求以char 大小的倍数表示。由于数组占用连续内存,char 的对齐要求必然是 1,即它的大小。现在,“1”可能代表 32 位内存,you 可能称之为“4 字节”,但就 C++ 环境而言,如果它是 char 占用的空间,那么它就是1 个字节。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-03
    • 1970-01-01
    • 2011-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多