Marshal.SizeOf和sizeof的区别

简介: sizeof在非Unsafe环境下只能用于预定义的一系列类型,如Int,Short等等。而在Unsafe环境下,sizeof可以被用于值类型,但是值类型中不可以有引用类型,否则C#编译器会报错: error CS0208: Cannot take the addre...

sizeof在非Unsafe环境下只能用于预定义的一系列类型,如Int,Short等等。而在Unsafe环境下,sizeof可以被用于值类型,但是值类型中不可以有引用类型,否则C#编译器会报错:

error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('SizeOf.Program.MyStruct')

而Marshal.SizeOf则是获得该类型被Marshal(转换,通常翻译为列集,指数据从一种类型转换到另外一种类型)到对应的非托管类型的大小。和sizeof不同,Marshal.SizeOf允许用在含有引用类型的值类型上:

 1: [StructLayout(LayoutKind.Sequential)]
 2: struct MyStruct
 3: {
 4: string s;
 5: }

Marshal.SizeOf(MyStruct)结果为4或者8,因为string被Marshal成char*。

如果用在不含有引用类型的值类型上,其结果也有可能和sizeof完全不一样,如对于下面的值类型:

 1: struct MyStruct
 2: {
 3: char b;
 4: }

sizeof(MyStruct)为2,而Marshal.SizeOf(typeof(MyStruct))结果则为1。这是因为在.NET中char总是Unicode,而缺省情况下char会被Marshal成8位的Ansi字符,因此结果不同。

反之,如果我们指定这个char被Marshal成short值(也就是UTF16),如下:

 1: [StructLayout(LayoutKind.Sequential)]
 2: struct MyStruct
 3: {
 4: [MarshalAs(UnmanagedType.I2)]
 5: char b;
 6: }

那么sizeof和Marshal.SizeOf结果均为2。MarshalAs这个Attribute可以影响Marshal.SizeOf的结果,而不能影响sizeof的结果。

一个有意思的情况是,如果值类型不含任何成员,如下:

 1: struct MyStruct
 2: {
 3: }

Sizeof和Marshal.SizeOf结果均为1,而不是0。这个结果和C++的结果是一致的。原因很简单:如果声明一个这样的数组,如果元素大小为0的话,那么每个元素都具有相同的地址,这是不为C++标准所允许的,和正常的非0的情况也不一致。.NET在这里采用和c++相同的规则,也认为空的值类型大小为1。

最后需要注意的是,如果MyStruct是模板:

 1: struct MyStruct
 2: {
 3: T a;
 4: }

如果对Marshal.SizeOf传入MyStruct或者MyStruct这样的类型,则抛出ArgumentException,因为Marshal.SizeOf完全不支持泛型。这个是历史遗留问题,从本质上来讲实例化的模板类型(MyStruct)应该是支持的,据说当时主要是没有时间加上对模板的支持。

同样的,sizeof也不支持模板类型,而且连MyStruct这样子的类型也不支持。C#编译器会对sizeof(MyStruct)报错:error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('SizeOf.Program.MyStruct')

From Blog:
http://www.cnblogs.com/jxnclyk/archive/2010/06/09/1754438.html

相关文章
|
14天前
|
编译器 C语言
sizeof,sizeof与strlen的区别
sizeof,sizeof与strlen的区别
19 0
sizeof,sizeof与strlen的区别
|
5月前
|
存储 C语言
关于sizeof介绍与分享给大家介绍
关于sizeof介绍与分享给大家介绍
|
5月前
|
Serverless
sizeof和strlen的区别【详解】
sizeof和strlen的区别【详解】
32 0
|
5月前
|
C语言
strlen和sizeof的区别
strlen和sizeof的区别
39 0
|
5月前
strlen与sizeof的区别
strlen与sizeof的区别
22 0
|
8月前
sizeof与strlen区别
sizeof是关键字,参数可以是各种数据(包括函数,类型,对象,数组,指针……)用于计算数据所占字节大小 strlen是函数,参数类型必须是字符型指针(char *),用于计算字符串,从字符串的第一个地址开始遍历,直到遇到‘\0’停止
49 0
|
11月前
|
存储 编译器 C++
C++ sizeof 的介绍
C++ sizeof 的介绍
90 0
|
C++
关于sizeof相关注意点
strlen是专门用来求字符串长度的,统计的是’\0’之前出现的字符个数,一定要找到’\0’才能结束,所以如果没有\0可能会存在越界访问问题
54 0
|
机器学习/深度学习 C语言
sizeof与strlen的区别和详解
sizeof与strlen的区别和详解