很少有人谈起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. [转]NHibernate之旅(3):探索查询之NHibernate查询语言(HQL)

    本节内容 NHibernate中的查询方法 NHibernate查询语言(HQL) 1.from子句 2.select子句 3.where子句 4.order by子句 5.group by子句 实例 ...

  2. Cocos2d-x java 通过jni调用c++的方法

    前面博客说到,cocos2d-x c++界面层运行在一个GLThread线程里面,严格的说是运行在Cocos2dxGLSurfaceView(继承自GLSurfaceView) 里面.opengl的渲 ...

  3. 在 slua 中使用更新的面向对象方案

    上一篇记录了我使用 Slua.Class 来实现面向对象扩展 C# 中得类,但实际使用中,更多地情况是直接在 lua 中定义基类然后扩展,于是触发了我重新思考下是否两种形式应该统一用一种,目前的方案中 ...

  4. 进程与线程(7) 进程间通信之信号量 (java os)

    花3分钟浏览一下: http://blog.csdn.net/liu765023051/article/details/8067601 1.生产者,消费者的列子. 2.互斥和同步到底什么东西? 互斥是 ...

  5. C++域宽设置

    域宽设置,域宽填充; 设置域宽, cout<<set[w-width](int n)<<被设置的输出内容 设置填充字符, cout<<setfill(char n) ...

  6. Area - POJ 1265(pick定理求格点数+求多边形面积)

    题目大意:以原点为起点然后每次增加一个x,y的值,求出来最后在多边形边上的点有多少个,内部的点有多少个,多边形的面积是多少. 分析: 1.以格子点为顶点的线段,覆盖的点的个数为GCD(dx,dy),其 ...

  7. [置顶] 分析Java死锁:分析jstack日志

    本文中我将展示一段垃圾代码,这段代码会产生死锁,这样围绕这段代码重点展示三种不同的方法来分析线程日志,从而得知什么地方有问题. 下面的讨论将用到两个类 Account 和 DeadlockDemo c ...

  8. composer 常用命令

    composer list 列出所有可用的命令 composer init 初始化 composer.json文件(就不劳我们自己费力创建啦),会要求输入一些信息来描述我们当前的项目,还会要求输入依赖 ...

  9. Hibernate查询方法总结

    1. HQL查询 HQL是Hiberante官方推荐的Hibernate检索方式,它使用类似SQL的查询语言,以面向对象的方式从数据库中查询.可以使用HQL查询具有继承.多态和关 联关系的数据.在检索 ...

  10. C# winform如何在textbox中判断输入的是字母还是数字?

    1.用正规式using System.Text.RegularExpressions; string pattern = @"^\d+(\.\d)?$";if(Text1.Text ...