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<t></t>
2: {
3: T a;
4: }
如果对Marshal.SizeOf传入MyStruct或者MyStruct<int>这样的类型,则抛出ArgumentException,因为Marshal.SizeOf完全不支持泛型。这个是历史遗留问题,从本质上来讲实例化的模板类型(MyStruct<int>)应该是支持的,据说当时主要是没有时间加上对模板的支持。</int></int>
同样的,sizeof也不支持模板类型,而且连MyStruct<int>这样子的类型也不支持。C#编译器会对sizeof(MyStruct<int>)报错:error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('SizeOf.Program.MyStruct<int>')</int></int></int>
作者:张羿
转载请注明出处
分享到:
相关推荐
在.NET框架中, Marshal 类是一个强大的工具,它提供了在托管代码(Managed Code)和非托管代码(Unmanaged Code)之间进行数据转换和交互的能力。Marshal类属于System.Runtime.InteropServices命名空间,是.NET平台...
IntPtr structPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WavHeader))); Marshal.Copy(bytes, 0, structPtr, Marshal.SizeOf(typeof(WavHeader))); WavHeader header = (WavHeader)Marshal....
Buffer.BlockCopy((byte*)&structArray[i], 0, byteCurrent, Marshal.SizeOf(), Marshal.SizeOf()); byteCurrent += Marshal.SizeOf(); } } return new MyStruct[count]; } ``` 这个方法中,我们使用`Marshal....
IntPtr structPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Operator))); Marshal.Copy(bytes, 0, structPtr, Marshal.SizeOf(typeof(Operator))); Operator operatorObj = (Operator)Marshal....
此方法中,`Marshal.SizeOf`用来获取结构体的大小;`Marshal.AllocHGlobal`分配内存空间;`Marshal.StructureToPtr`将结构体复制到指针所指向的内存区域;`Marshal.Copy`则负责将内存中的数据复制到字节数组中。 ##...
int size = Marshal.SizeOf(structObj); byte[] bytes = new byte[size]; IntPtr structPtr = Marshal.AllocHGlobal(size); Marshal.StructureToPtr(structObj, structPtr, false); Marshal.Copy(structPtr, ...
Dim lParam As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(cds)) Marshal.StructureToPtr(cds, lParam, False) SendMessage(hWndReceiver, &H4A, 0, lParam) ' WM_COPYDATA 消息码 Marshal.FreeHGlobal(lParam) ...
IntPtr intptrStruct = Marshal.AllocCoTaskMem(Marshal.SizeOf(struct_IPI)); // Converting structure to IntPtr Marshal.StructureToPtr(struct_IPI, intptrStruct, true); bool iReturn = ...
int size = Marshal.SizeOf(objStruct); byte[] buffer = new byte[size]; IntPtr ipStruct = Marshal.AllocHGlobal(size); Marshal.StructureToPtr(objStruct, ipStruct, false); Marshal.Copy(ipStruct, ...
IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char)); uint bytesReturned = GetPrivateProfileSectionNames(pReturnedString, MAX_BUFFER, iniFile); if (bytesReturned != 0) {...
dm.dmSize= (short)Marshal.SizeOf(typeof(DEVMODE)); dm.dmPelsWidth = 1024; dm.dmPelsHeight= 768; dm.dmDisplayFrequency=85; dm.dmFields = DEVMODE.DM_PELSWIDTH | DEVMODE.DM_PELSHEIGHT | DEVMODE.DM_...
通过`sizeof`和`Marshal.SizeOf`,开发者可以获取类型或实例在内存中占用的空间,从而进行更精细的内存管理。不过,需要注意内存对齐、平台差异等因素对实际大小的影响。在实际应用中,合理利用这些知识可以提升程序...
dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE)); if (chMode == 1) { dm.dmPelsWidth = 1600; dm.dmPelsHeight = 1024; dm.dmDisplayFrequency = 85; } else if (chMode == 2) { dm.dmPelsWidth = 1024; dm....
var ptrByteArray1Size = Marshal.SizeOf(ptrByteArray1); var ptrByteArray1Intptr = Marshal.AllocHGlobal(ptrByteArray1Size); Marshal.StructureToPtr(ptrByteArray1, ptrByteArray1Intptr, true); ...
SendInput(1, New INPUT() {input}, Marshal.SizeOf(input)) '按下Space键 input.ki.wVk = &H20 'Space键的虚拟键码 SendInput(1, New INPUT() {input}, Marshal.SizeOf(input)) '释放Space键 input.ki....
SendInput(1, new INPUT[] { input }, Marshal.SizeOf(input)); input.ki.wVk = (ushort)Keys.R; input.ki.dwFlags = 0; // Key down SendInput(1, new INPUT[] { input }, Marshal.SizeOf(input)); input....
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(p)); try { // 将结构体数据复制到非托管内存 Marshal.StructureToPtr(p, ptr, false); // 读取非托管内存中的数据 PERSON pFromPtr = (PERSON)Marshal....
这里使用了`Marshal.SizeOf`计算结构体的大小,并通过`Marshal.StructureToPtr`将结构体复制到内存的字节数组中。 3. **字节数组转结构体**:创建一个方法将字节数组还原为结构体。 ```csharp public static ...
si.cb = Marshal.SizeOf(si); StringBuilder sb = new StringBuilder(@"C:\WINDOWS\notepad.exe c:\1.txt"); if (CreateProcess(null,sb, IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, IntPtr.Zero, ref si...
IntPtr intptr = Marshal.AllocHGlobal(Marshal.SizeOf(vga)); Marshal.StructureToPtr(vga, intptr, true); // 将结构体复制到非托管内存 // 在此发送 intptr 指针给目的方 Marshal.FreeHGlobal(intptr); // 释放...