存储在标题和浪费空间中的C#和CLR中的值类型

时间:2017-03-08 16:45:09

标签: c# clr

我只是第二年计算机科学家学生,他正在努力学习更多知识。我正在读一本c#书:" c#简而言之"我遇到了关于在c#中标题存储的这一段。

  

值类型实例恰好占用存储其字段所需的内存。在   在这个例子中,Point需要8个字节的内存:

     
    

struct Point     {     int x; // 4字节     int y; // 4字节     }

  
     

从技术上讲,CLR将类型中的字段定位在   地址是字段大小的倍数(最大值)   八个字节)。因此,以下实际上消耗16个字节   内存(第一个字段后面的七个字节“浪费”):   struct A {byte b;长l; }   您可以使用StructLayout覆盖此行为   属性

我的第一个问题是:为什么只有16个字节?为什么不是8或32或其他数字是8的倍数

我的第二个问题是:为什么会浪费

3 个答案:

答案 0 :(得分:2)

计算机体系结构将最小可寻址空间确定为“单词”。因此,例如,在32位架构上,该字是32位或4字节。它是64位架构的两倍。处理器操作适用于单词,而不是字节。

因此,想象一下32位架构上的struct MyStruct {byte a; long b;},这需要3个字(12个字节)。在64位架构上,这需要16个字节。

// 8-bit word size (3 1-byte words or 3 bytes) - this is the most compact it can be, but we don't use 8-bit processors.
|1|1|2|3|4|5|6|7|8|
|a|b|b|b|b|b|b|b|b|

// 32-bit word size (3 4-byte words or 12 bytes)
|1234|1234|1234|
|a---|bbbb bbbb|

// 64-bit word size (2 8-byte words or 16-bytes)
|12345678|12345678|
|a-------|bbbbbbbb|

答案 1 :(得分:1)

在C#中,intSystem.Int32的别名,它是一个32位有符号整数,为4个字节。

当与机器字边界对齐时,处理器通常更有效地访问64位边界的内存,因此编译器可能会将结构的成员与心中的成员对齐,并且实际上在物理空间中留下空白空间结构使其更快地访问它们。

答案 2 :(得分:1)

struct A { byte b; long l; }

上述struct的内存布局可能如下所示:

  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| b |   |   |   |   |   |   |   | l | l | l | l | l | l | l | l |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

byte b放在struct的开头(起始索引0)。它占用一个字节,因此下一个字段的起始索引为1(或更大)。 long l将占用8个字节,因此它必须从8的倍数开始。运行时将尝试将字段放在下一个可能的索引处,以使结构大于它需要是。这就是为什么它将被放置在偏移8的起始位置。

因此,字节1到7将不会被struct A的任何字段占用。它们不被A的任何字段使用,并且由于.NET对象不会在内存中相互叠加,因此没有任何东西可以使用或访问这7个字节。它们专门用于A的实例,但不包含任何内容,因此它们的空间被有效地浪费了。