int size = sizeof (int); //4个字节
注意点:sizeof 运算符仅适用于值类型,而不适用于引用类型。sizeof 运算符只能在不安全代码块中使用。如下面的代码将无法编译通过:
public struct TestStuct{}
int size = sizeof(new TestStuct());
编译后,提示:
错误 1 “ConsoleApplication3.TestStuct”没有预定义的大小,因此 sizeof 只能在不安全的上下文中使用(请考虑使用 System.Runtime.InteropServices.Marshal.SizeOf)
修改为Marshal.SizeOf方法,改方法返回对象的非托管大小(以字节为单位)。参数可以是引用类型或装箱的值类型。布局必须是连续的或显式的。
int size = Marshal.SizeOf(new TestStuct()); //1个字节
接下来来验证引用类型:
由于不能作为非托管结构进行封送处理;无法计算有意义的大小或偏移量。所有下面的代码在运行的时候,会抛出异常。
public class Student
{
}
int size = Marshal.SizeOf(new Student());
需要给Student类,加上一个StructLayoutAttribute,来控制Student类的数据字段的物理布局。修改代码为:
[StructLayout(LayoutKind.Sequential)]
public class Student
{
}
int size = Marshal.SizeOf(new Student()); //1个字节
LayoutKind 默认值为Auto.
结论:
1:对于托管对象是没有办法直接获取到一个对象所占的内存大小。
2:非托管对象,可以使用Marshal.SizeOf
3:对内置类型,如int,long,byte等使用sizeof
扩展:
有人提出使用二进制序列化,将一个对象序列化成一个MemoryStream,然后返回MemoryStream.Length,经过验证是不可以的。
验证代码如下:
[Serializable]
public class Student
{
}
private static long GetObjectSize(object o)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, o);
using (var fileStream = new FileStream(@"D:\Student.txt", FileMode.OpenOrCreate, FileAccess.Write))
{
var buffer = stream.ToArray();
fileStream.Write(buffer, 0, buffer.Length);
fileStream.Flush();
}
return stream.Length;
}
}
var student = new Student();
long size = GetObjectSize(student); //139个字节
Student.txt保存的文本信息如下所示,通过文本信息,可以得知多出来的100多个字节,估计是就是这一串字符串吧。
JConsoleApplication3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null ConsoleApplication3.Student
//https://ask.csdn.net/questions/164716
有下面一段程序
namespace ConsoleApplication2
{
class Program
{
public struct ss
{
private char s;
private char e;
private char w;
private char q;
private char d;
private char g;
// private int a;
}
static void Main(string[] args)
{
char cc = 'f';
ss s = new ss();
Console.WriteLine(System.Runtime.InteropServices.Marshal.SizeOf(cc));
Console.WriteLine(sizeof(char));
Console.WriteLine(System.Runtime.InteropServices.Marshal.SizeOf(s));
}
}
}
输出结果为
1
2
6
问题一:为什么都是char,System.Runtime.InteropServices.Marshal.SizeOf(cc)输出1,而 Console.WriteLine(sizeof(char));输出2呢?
问题二:对于那个struct,输出为6,但是再加入字段private int a;为什么大小为12了呢?a占4个,为什么签名的6个char变成占了8个啊?不是之前输出是6么?
问题一:对于所有其他类型(包括 struct),sizeof 运算符只能在不安全代码块中使用。虽然可以使用 Marshal.SizeOf 方法,但该方法返回的值和 sizeof 返回的值并不总是相同的。Marshal.SizeOf 在已封送处理类型后返回大小,而 sizeof 返回公共语言运行时分配的大小(包括任何空白)。
c sharp 中用的是unicode编码,所以一个char占用两个字节(比如表示一个汉字,需要两个字节)。而在非托管的语言中,字符编码都是8位(比如美国国家标准协会的编码ansi).。
问题二、要从C语言谈起。C语言里面struct的空间大小有个对齐原则,以占据空间最大的那个类型的大小的倍数对齐,也就是在这里,int a占了4字节,那么最终struct必须占据4的
最小倍数,此处正常算出来是10,但是10不是4的倍数,必须补足到12.C#也是一样的道理。这是一种优化机制或者说一种规定罢了。
//https://zhidao.baidu.com/question/128480617.html
//以下三个结构
public struct myStruct
{
public long lval;//8
public int ival;//4
}//8+4 = 12 => 字节对齐 16
public struct myStruct1
{
public long lval;//8
public int ival;//4
public string str;//4
}//8+4+4=16 => 字节对齐 16
public struct myStruct2
{
public long lval;//8
public int ival;//4
public object obj;//4
}//8+4+4=16 => 字节对齐 16
public struct myStruct3
{
public long lval;//8
public int ival;//4
public string str;//4
public object obj;//4
}//8+4+4+4=20 => 字节对齐 24
class Program
{
static void Main(string[] args)
{
int size;
size = sizeof(int);//返回4
Console.WriteLine("int 型变量占用" + size.ToString() + "字节");
size = sizeof(long);//返回8
Console.WriteLine("long 型变量占用" + size.ToString() + "字节");
unsafe
{
size = sizeof(myStruct); //据说是存在 字节对齐,所以结果为16
}
Console.WriteLine("myStruct 型变量占用" + size.ToString() + "字节");
//Marshal.SizeOf 获取已封送处理类型后的大小,而sizeof返回CLR分配的大小
size = System.Runtime.InteropServices.Marshal.SizeOf(new myStruct());//返回16
Console.WriteLine("Marshal.SizeOf方法获得的myStruct占用" + size + "字节");
size = System.Runtime.InteropServices.Marshal.SizeOf(new mySturct1()); //返回16
Console.WriteLine("Marshal.SizeOf方法获得的myStruct1占用" + size + "字节");
size = System.Runtime.InteropServices.Marshal.SizeOf(new mySturct2()); //返回16
Console.WriteLine("Marshal.SizeOf方法获得的myStruct2占用" + size + "字节");
size = System.Runtime.InteropServices.Marshal.SizeOf(new mySturct3()); //返回24
Console.WriteLine("Marshal.SizeOf方法获得的myStruct3占用" + size + "字节");
Console.ReadKey();
}
}