【问题标题】:Size of a C++ array in 64 vs 32 bit environment64 位与 32 位环境中 C++ 数组的大小
【发布时间】:2011-04-24 11:52:02
【问题描述】:

假设我有一个定义如下的类

class foo
{
    char [10] bar;
}

假设没有填充/打包,在 64 位环境中与 32 位环境相比,此类的大小有何不同。

我相信 64 位版本的类的长度会多 4 个字节,因为:

  1. 该类必须包含一个 char* 才能指向数组 bar 的开头
  2. char* 在 64 位环境中为 8 个字节,而在 32 位环境中为 4 个字节

我说的对吗?

谢谢!

关于数组实际工作原理的进一步问题 如果声明数组时没有存储指针,那怎么能从数组名中得到地址,然后做bar[0]、bar[1]之类的事情呢?

【问题讨论】:

  • 如果没有存储指针,怎么能从数组名bar中得到一个地址,然后做bar[0]、bar[1]之类的事情?
  • 因为 C++ 会隐式地将其视为指向 bar 的指针。基本上,你可以像&bar[0] 一样使用bar
  • "如果int i;不存储地址,你怎么能从&i这样的表达式中得到地址?"正在问你刚才问的完全相同的问题。一个数组有一个地址,因为它在内存中的某个地方,就像不在寄存器中的所有其他东西一样(而且我已经很久没有看到register 关键字了,因为编译器无论如何都做得更好)。我知道这很令人困惑,因为您可以使用数组索引语法来取消引用指针。这是关于 C 和 C++ 更令人困惑的问题之一。

标签: c++ 64-bit 32-bit 32bit-64bit


【解决方案1】:

不,你不是。 char [] bar; 甚至无法编译,char bar[10]; 是正确的语法,不,不存储指针,sizeof(char) 始终为 1,sizeof bar 始终为 10,无论架构如何。

现在回答您的其他问题: 您必须了解左值和右值以及左值到右值转换的概念。通常左值到右值的转换“什么都不做”。一个例外是 T 数组的左值到右值转换是转换为指向 T 的指针,该指针指向数组的第一个元素。

另外,一个按值获取 T 数组的函数声明等价于一个使用指向 T 的指针的函数声明。

【讨论】:

  • sizeof(bar) 无论如何都会是 10,但 sizeof(foo) 可能不会(而且通常不会)。
  • @Jerry Coffin> wk1989 确实说过“假设没有填充/包装”。
  • 我经常在 sizeof(char) == 2 的机器上工作。外面的世界很大......
  • @florin:在这种情况下,您在不遵守标准的机器(或者更确切地说,编译器)上工作。在 C++ 中,sizeof(char) 为 1。但是它可能大于 8 位。
  • @Armen:C 标准第 5.2.4.2.1 节给出的最小范围为 256。 C++ 标准几乎呼应了这一要求(明显的区别在于它主要谈论std::numeric_limits<unsigned char>::max() 而不是UINT_MAX)。
【解决方案2】:

sizeof(char) 在 C++ 标准中定义为 1,无论您的架构是什么。您的结构是 10 个字符的数组,而不是指向数组的指针。

另外,正确的声明应该是char bar[10]

您可能正在考虑 char *bar - 现在这将是 4 字节与 32 位与 64 位中的 8 字节。

【讨论】:

  • 您能否指出标准中指定 sizeof(char) == 1 的部分?我经常在 sizeof(char) == 2 的机器上工作。
  • @florin: §5.3.3/1: "sizeof(char), sizeof(signed char) 和 sizeof(unsigned char) 为 1。sizeof 应用于任何其他基本类型 (3.9 .1) 是实现定义的。”
  • 哈,在 stackoverflow 上的另一个问题中对此进行了讨论,我认为它有一个链接。我看看能不能挖出来。
  • @David Thornley:我在一些嵌入式 DSP 上工作,有时我必须移植一些对大小、填充和对齐做出错误假设的代码。追逐那些虫子可不好玩。
【解决方案3】:

您可能会看到差异的一种方式是,如果编译器决定在数组之后插入一些填充,那么如果您要创建这些对象的数组,每个对象都会很好地对齐。例如,在 32 位目标上,它可能会将其填充为 12 个字节,但在 64 位目标上则改为 16 个字节。

但是,如果没有填充,两者的大小将相同——您没有定义指针,因此指针大小的差异在这里没有影响。

【讨论】:

    【解决方案4】:

    你给出的例子在 64 位环境下不会变大。

    class foo
    {
        char bar[10];
    };
    

    不过,它也没什么用,因为它没有公共成员。

    许多类看起来更像这样:

    class foo2
    {
    public:
        char bar[10];
        virtual ~foo2() {}
    };
    

    具有任何虚拟成员的类(例如 foo2 具有)将随着指针大小的增长而增长。但是,对于大多数编译器,无论有多少虚拟成员,都只有一个指针。

    无论哪种方式,这只是您创建大量(> 说 20000 个实例)的类的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      • 2016-06-01
      • 1970-01-01
      • 2015-03-26
      相关资源
      最近更新 更多