Net的struct的内存对齐问题

很少有人谈起struct的内存对齐问题, 就是在很多C#书中, 也很少提及. 但在实际应用中, 如果不注意内存对齐, struct比较大的话, 则会浪费一定的内存.
    先从一个实例看起.
 public unsafe struct MyStruct1
 {
  byte b;
  string s;
  int i;
  char c;
 }
    在这个struct中, 各个成员的字节数为, b:1, s:4, i:4, c:1. s为指针, 所以为4个字节. 把这些成员的字节数加起来应该为10个字节, 很多人都是这么理所当然的认为.但实际上呢, 却并非如此. 可以做一个测试.
 public class test
 {
  
  public static void Main()
  {
   MyValue mv = new MyValue();
   int size = System.Runtime.InteropServices.Marshal.SizeOf(mv);
   Console.WriteLine(size.ToString());
  }
  
 }
    结果显示为16个字节, 与所想的有一定差距. 为什么会出现这种情况呢, 这就涉及到了内存对齐的问题struct member alignment.
    在编译器中使用内存对齐, 是为了提高程序的性能. 访问未对齐的内存, 处理器需要做两次的内存访问, 但是, 对齐的内存, 仅需一次. 因为编译器将struct与自然边界对象. 自然边界为偶数地址, 可以被4或8整除. 一个struct的成员字节跨越了自然边界数, 认为是未对齐, 如果没有跨越, 可以访问一次就能读取.
    我们再来分析上面的struct. struct在分配内存的时候, 各个成员的地址是相邻的. C#中alignment的字节数为4个字节. 因此, 它将4个字节作为一个分配单元. 如果相邻的几个成员字节数相加不超过一个分配单元, 则这几个成员都会在一个分配单元中. 上面的struct中, b为1个字节, s为4个字节, 相加后超过了一个分配单元的大小, 因此它们被分配到两个单元中, 每个所占空间为4个字节. 成员i和c的情况亦是如此. 因此, 上面的struct被分配了4个单元, 所占内存就为16个字节, 而不是简单相加所得到的10个字节.
    现在我们把上面的struct做一个调整, 将byte类型和char类型相邻.
 public unsafe struct MyStruct2
 {
  byte b;
  char c;
  string s;
  int i;
 }
    现在再来测试一下它的内存大小, 结果为12. 它变小了, 少了4个字节. 按照上面所讲的原理, b和c相加, 没有超过4个字节, 因此它们被分配到一个单元。

以上文章来自:核桃的博客

另外一篇C语言的相关文章:xingoo-谁的青春不迷茫

 测试代码:

Console.WriteLine("char size:" + sizeof(char));
            Console.WriteLine("int size:" + sizeof(int));
            Console.WriteLine("byte size:" + sizeof(int));

            node1 n1 = new node1();
            node2 n2 = new node2();
            node3 n3 = new node3();
            node4 n4 = new node4();
            int size1 = System.Runtime.InteropServices.Marshal.SizeOf(n1);
            int size2 = System.Runtime.InteropServices.Marshal.SizeOf(n2);
            int size3 = System.Runtime.InteropServices.Marshal.SizeOf(n3);
            int size4 = System.Runtime.InteropServices.Marshal.SizeOf(n4);
            Console.WriteLine("Struct Sort Value Type:");
            Console.WriteLine("byte string int char:" + size1);
            Console.WriteLine("byte char string int:" + size2);
            Console.WriteLine("char int char:" + size3);
            Console.WriteLine("int char char:" + size4);

结果:

Net的struct的内存对齐问题

看来的确是这样的。