很少有人谈起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的内存对齐问题的更多相关文章

  1. c语言中struct的内存对齐

    为了让CPU能够更舒服地访问到变量,struct中的各成员变量的存储地址有一套对齐的机制.这个机制概括起来有两点:第一,每个成员变量的首地址,必须是它的类型的对齐值的整数倍,如果不满足,它与前一个成员 ...

  2. C 语言结构体 struct 及内存对齐

    struct 结构体 对于复杂的数据类型(例如学生.汽车等),C 语言允许我们将多种数据封装到一起,构成新类型. 跟面向对象语言中的对象相比,结构体只能包含成员变量,不支持操作. #include & ...

  3. C struct的内存对齐

    说明:如果你看到了这篇,请略过. struct是复合类型. 其中的成员在内存中的分布都是对齐的. 这个对齐的意思是,struct的sizeof运算结果必定是其最大类型长度的整数倍. --注意,如果st ...

  4. 内存对齐-C语言struct内存占用问题

    转1个写的比较全面的. http://hubingforever.blog.163.com/blog/static/17104057920122256134681/ 本文编辑整理自:http://hi ...

  5. struct内存对齐1:gcc与VC的差别

    struct内存对齐:gcc与VC的差别 内存对齐是编译器为了便于CPU快速访问而采用的一项技术,对于不同的编译器有不同的处理方法. Win32平台下的微软VC编译器在默认情况下采用如下的对齐规则:  ...

  6. 【转】C/C++ struct/class/union内存对齐

    原文链接:http://www.cnblogs.com/Miranda-lym/p/5197805.html struct/class/union内存对齐原则有四个: 1).数据成员对齐规则:结构(s ...

  7. 利用php unpack读取c struct的二进制数据,struct内存对齐引起的一些问题

    c语言代码 #include <stdio.h> struct test{ int a; unsigned char b; int c; }; int main(){ FILE *fp; ...

  8. struct内存对齐

    内存对齐其实是为了在程序运行的时候更快的查找内存而做的一种编译器优化. 我们先看这样一个例子: #include <iostream> using namespace std; struc ...

  9. 内存对齐与ANSI C中struct型数据的内存布局 【转】

    转自:http://blog.chinaunix.net/uid-25909619-id-3032209.html 当在C中定义了一个结构类型时,它的大小是否等于各字段(field)大小之和?编译器将 ...

随机推荐

  1. C#中类的默认访问是私有的

    如果类前面没有访问修饰符的话,那里面的成员默认是私有private. 下面的代码是从MSDN上拷的,那个d它说明了私有:class Employee{private int i;double d; / ...

  2. java NIO 资料总结

    1.http://developer.51cto.com/art/201204/328340.htm 2.http://ifeve.com/file-channel/并发编程网系列 3 http:// ...

  3. Stand-up meeting

    A stand-up meeting (or simply "stand-up") is a daily team-meeting held to provide a status ...

  4. linux IPC总结——管道

    管道 管道是unix ipc的最古老形式,是一种在内存中的特殊文件,只能在具有公共祖先的进程之间使用(即父子进程,兄弟进程). 管道由pipe函数创建 #include <unistd.h> ...

  5. Yii PHP 框架分析 (一)

    Yii PHP 框架分析 (一)作者:wdy http://hi.baidu.com/delphiss/blog/item/f7da86d787adb72506088b4b.html 基于yii1.0 ...

  6. 【转】终极 Shell

    Post navigation ← PreviousNext → 终极 Shell Posted on 2013 年 7 月 23 日 在开始今天的 MacTalk 之前,先问两个问题吧: 1.相对于 ...

  7. java nio之Buffer(一)

    Buffer是一个包装了基本数据元素数组的对象,它以及它的子类定义了一系列API用于处理数据缓存. 一.属性 Buffer有四个基本属性: 1.capacity  容量,buffer能够容纳的最大元素 ...

  8. gist c code

    http://lear.inrialpes.fr/software Fisher kernel: http://vision.caltech.edu/~sbranson/code/index.html ...

  9. [置顶] sql 向另一个表导数据

    1.如果目的表已经存在: 这两个表结构必须一致 insert into table1 select * from tabel2 2.如果目的表不存在: 这个类似与克隆表 select * into t ...

  10. AndroidUI组件之ActionBar--基于下拉的导航方式

      在上一篇关于ActionBar的博文中.我们知道了ActionBar是Android3.0的重要更新之中的一个.本篇博文就来写一个开发中经经常使用到的样例.用ActionBar提供基于下拉的导航方 ...