国产午夜成人免费看片无遮挡_日本免费xxxx色视频_免费人成网上在线观看_黄网址在线永久免费观看

當前位置:雨林木風下載站 > 技術開發教程 > 詳細頁面

在 C# 中處理結構內的數組

在 C# 中處理結構內的數組

更新時間:2022-05-01 文章作者:未知 信息來源:網絡 閱讀次數:

在 C/C++ 代碼中,大量摻雜著包括普通類型和數組的結構,如定義 PE 文件頭結構的 IMAGE_OPTIONAL_HEADER 結構定義如下:


以下內容為程序代碼:

typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16

typedef struct _IMAGE_OPTIONAL_HEADER {

WORD Magic;

//...

DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];

} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;



在 C/C++ 中這樣在結構中使用數組是完全正確的,因為這些數組將作為整個結構的一部分,在對結構操作時直接訪問結構所在內存塊。但在 C# 這類語言中,則無法直接如此使用,因為數組是作為一種特殊的引用類型存在的,如定義:
以下內容為程序代碼:

public struct IMAGE_DATA_DIRECTORY
{
public uint VirtualAddress;
public uint Size;
}

public struct IMAGE_OPTIONAL_HEADER
{
public const int IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;

public ushort Magic;

//...

public uint NumberOfRvaAndSizes;

public IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
}



在 C# 中這樣定義結構中的數組是錯誤的,會在編譯時獲得一個 CS0650 錯誤:

以下為引用:

error CS0650: 語法錯誤,錯誤的數組聲明符。若要聲明托管數組,秩說明符應位于變量標識符之前




如果改用 C# 中引用類型的類似定義語法,如
以下內容為程序代碼:

public struct IMAGE_OPTIONAL_HEADER
{
public const int IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;

public ushort Magic;

//...

public uint NumberOfRvaAndSizes;

public IMAGE_DATA_DIRECTORY[] DataDirectory = new IMAGE_DATA_DIRECTORY[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
}



則得到一個 CS0573 錯誤:

以下為引用:

error CS0573: “IMAGE_OPTIONAL_HEADER.DataDirectory” : 結構中不能有實例字段初始值設定項




因為結構內是不能夠有引用類型的初始化的,這與 class 的初始化工作不同。如此一來只能將數組的初始化放到構造函數中,而且結構還不能有無參數的缺省構造函數,真是麻煩,呵呵
以下內容為程序代碼:

public struct IMAGE_OPTIONAL_HEADER
{
public const int IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;

public ushort Magic;

public uint NumberOfRvaAndSizes;

public IMAGE_DATA_DIRECTORY[] DataDirectory;

public IMAGE_OPTIONAL_HEADER(IntPtr ptr)
{
Magic = 0;
NumberOfRvaAndSizes = 0;

DataDirectory = new IMAGE_DATA_DIRECTORY[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
}
}



這樣一來看起來似乎能使了,但如果使用 Marshal.SizeOf(typeof(IMAGE_OPTIONAL_HEADER)) 看看就會發現,其長度根本就跟 C/C++ 中定義的長度不同。問題還是在于結構中數組,雖然看起來此數組是定義在結構內,但實際上在此結構中只有一個指向 IMAGE_DATA_DIRECTORY[] 數組類型的指針而已,本應保存在 DataDirectory 未知的數組內容,是在托管堆中。
于是問題就變成如何將引用類型的數組,放在一個值類型的結構中。

解決的方法有很多,如通過 StructLayout 顯式指定結構的長度來限定內容:
以下內容為程序代碼:

[StructLayout(LayoutKind.Sequential, Size=XXX)]
public struct IMAGE_OPTIONAL_HEADER
{
public const int IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;

public ushort Magic;

public uint NumberOfRvaAndSizes;

public IMAGE_DATA_DIRECTORY DataDirectory;
}



注意這兒 StructLayout 中 Size 指定的是整個結構的長度,因為 DataDirectory 已經是最后一個字段,故而數組的后 15 個元素被保存在未命名的堆棧空間內。使用的時候稍微麻煩一點,需要一次性讀取整個結構,然后通過 unsafe 代碼的指針操作來訪問 DataDirectory 字段后面的其他數組元素。
這種方法的優點是定義簡單,但使用時需要依賴 unsafe 的指針操作代碼,且受到數組字段必須是在最后的限制。當然也可以通過 LayoutKind.Explicit 顯式指定每個字段的未知來模擬多個結構內嵌數組,但這需要手工計算每個字段偏移,比較麻煩。

另外一種解決方法是通過 Marshal 的支持,顯式定義數組元素所占位置,如
以下內容為程序代碼:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct IMAGE_OPTIONAL_HEADER
{
public const int IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;

public ushort Magic;

public uint NumberOfRvaAndSizes;

[MarshalAs(UnmanagedType.ByValArray, SizeConst=IMAGE_NUMBEROF_DIRECTORY_ENTRIES)]
public IMAGE_DATA_DIRECTORY[] DataDirectory;
}



這種方法相對來說要優雅一些,通過 Marshal 機制支持的屬性來定義值數組語義,使用起來與普通的數組區別不算太大。上述數組定義被編譯成 IL 定義:
以下內容為程序代碼:

.field public marshal( fixed array [16]) valuetype IMAGE_DATA_DIRECTORY[] DataDirectory



雖然類型還是 valuetype IMAGE_DATA_DIRECTORY[],但因為 marshal( fixed array [16]) 的修飾,此數組已經從引用語義改為值語義。不過這樣做還是會受到一些限制,如不能多層嵌套、使用時性能受到影響等等。

除了上述兩種在結構定義本身做文章的解決方法,還可以從結構的操作上做文章。

此類結構除了對結構內數組的訪問外,主要的操作類型就是從內存塊或輸入流中讀取整個結構,因此完全可以使用 CLR 提高的二進制序列化支持,通過實現自定義序列化函數來完成數據的載入和保存,如:
以下內容為程序代碼:


[Serializable]
public struct IMAGE_OPTIONAL_HEADER : ISerializable
{
public const int IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;

public ushort Magic;

public uint NumberOfRvaAndSizes;

public IMAGE_DATA_DIRECTORY[] DataDirectory;

public IMAGE_OPTIONAL_HEADER(IntPtr ptr)
{
Magic = 0;
NumberOfRvaAndSizes = 0;

DataDirectory = new IMAGE_DATA_DIRECTORY[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
}

[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
// 完成序列化操作
}
}



這種解決方法可以將結構的載入和存儲,與結構的內部表現完全分離開來。雖然結構內部保存的只是數組引用,但用戶并不需關心。但缺點是必須為每個結構都編寫相應的序列化支持代碼,編寫和維護都比較麻煩。

與此思路類似的是我比較喜歡的一種解決方法,通過一個公共工具基類以 Reflection 的方式統一處理,如:
以下內容為程序代碼:

public class IMAGE_OPTIONAL_HEADER : BinaryBlock
{
public const int IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;

public ushort Magic;

public uint NumberOfRvaAndSizes;

public IMAGE_DATA_DIRECTORY[] DataDirectory = new IMAGE_DATA_DIRECTORY[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
}



注意原本的 struct 在這兒已經改為 class,因為通過這種方式已經沒有必要非得固守值類型的內存模型。BinaryBlock 是一個公共的工具基類,負責通過 Reflection 提供類型的載入和存儲功能,如
以下內容為程序代碼:

public class BinaryBlock
{
private static readonly ILog _log = LogManager.GetLogger(typeof(BinaryBlock));

public BinaryBlock()
{
}

static public object LoadFromStream(BinaryReader reader, Type objType)
{
if(objType.Equals(typeof(char)))
{
return reader.ReadChar();
}
else if(objType.Equals(typeof(byte)))
{
return reader.ReadByte();
}
//...
else if(objType.Equals(typeof(double)))
{
return reader.ReadDouble();
}
else if(objType.IsArray)
{
// 處理數組的情況
}
else
{
foreach(FieldInfo field in ClassType.GetFields())
{
field.SetValue(obj, LoadFromStream(...));
}
}

return true;
}

public bool LoadFromStream(Stream stream)
{
return LoadFromStream(new BinaryReader(stream), this);
}
}



LoadFromStream 是一個嵌套方法,負責根據指定字段類型從流中載入相應的值。使用時只需要對整個類型調用此方法,則會自動以 Reflection 機制,遍歷類的所有字段進行處理,如果有嵌套定義的情況也可以直接處理。使用此方法,類型本身的定義基本上就無需擔心載入和存儲機制,只要從 BinaryBlock 類型繼承即可。有興趣的朋友還可以對此類進一步擴展,支持二進制序列化機制。

此外 C# 2.0 中為了解決此類問題提供了一個新的 fixed array 機制,支持在結構中直接定義內嵌值語義的數組,如
以下內容為程序代碼:

struct data
{
int header;
fixed int values[10];
}



此結構在編譯時由編譯器將數組字段翻譯成一個外部值類型結構,以實現合適的空間布局,如
以下內容為程序代碼:

.class private sequential ansi sealed beforefieldinit data
extends [mscorlib]System.ValueType
{
.class sequential ansi sealed nested public beforefieldinit '<values>e__FixedBuffer0'
extends [mscorlib]System.ValueType
{
.pack 0
.size 40
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 [img]/images/wink.gif[/img]
.field public int32 FixedElementField
} // end of class '<values>e__FixedBuffer0'

.field public int32 header
.field public valuetype data/'<values>e__FixedBuffer0' values
.custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, int32) = ( ...)
} // end of class data



可以看到 values 字段被編譯成一個值類型,而值類型本身使用的是類似于上述第一種解決方法的思路,強行限制結構長度。而在使用時,也完全是類似于第一種解決方法的 unsafe 操作,如對此數組的訪問被編譯成 unsafe 的指針操作:
以下內容為程序代碼:

// 編譯前
for(int i=0; i<10; i++)
d.values[i] = i;

// 編譯后
for(int i=0; i<10; i++)
&data1.values.FixedElementField[(((IntPtr) i) * 4)] = i;



不幸的是這種方式必須通過 unsafe 方式編譯,因為其內部都是通過 unsafe 方式實現的。而且也只能處理一級的嵌套定義,如果將 IMAGE_OPTIONAL_HEADER 的定義轉換過來會得到一個 CS1663 錯誤:
以下內容為程序代碼:

error CS1663: Fixed sized buffer type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double




Eric Gunnerson 有篇文章, Arrays inside of structures,簡要介紹了 C# 2.0 中的這種有限度的

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統下載排行

国产午夜成人免费看片无遮挡_日本免费xxxx色视频_免费人成网上在线观看_黄网址在线永久免费观看

  • <label id="pxtpz"><meter id="pxtpz"></meter></label>
      1. <span id="pxtpz"><optgroup id="pxtpz"></optgroup></span>

        国产激情精品久久久第一区二区 | 欧美日韩高清一区二区| 久久久精品国产免费观看同学| 久久66热偷产精品| 亚洲国产精品国自产拍av| 91亚洲国产成人精品一区二区三 | 国产成人免费视频一区| 亚洲欧美日韩在线| 欧美丰满少妇xxxxx高潮对白| 日本三级韩国三级欧美三级| 亚洲精品一区二区三区精华液| 成人一区二区三区视频| 亚洲gay无套男同| 久久综合99re88久久爱| 91丨porny丨蝌蚪视频| 欧美aaa在线| 亚洲摸摸操操av| 日韩精品中文字幕在线不卡尤物| a在线欧美一区| 免费av网站大全久久| 自拍视频在线观看一区二区| 日韩欧美激情四射| 色婷婷精品久久二区二区蜜臂av| 麻豆成人91精品二区三区| 亚洲免费资源在线播放| 久久久久久免费网| 91精品免费在线观看| 91麻豆蜜桃一区二区三区| 美女网站色91| 亚洲制服丝袜在线| 中文字幕国产一区二区| 欧美一区二区三区视频免费| eeuss国产一区二区三区| 美日韩一区二区三区| 亚洲欧美日本在线| 国产精品你懂的在线欣赏| 日韩午夜在线观看视频| 在线视频观看一区| 国产sm精品调教视频网站| 久久99国产精品麻豆| 亚洲成人黄色影院| 亚洲美女精品一区| 最新不卡av在线| 国产精品免费视频一区| 久久久精品影视| 欧美www视频| 555夜色666亚洲国产免| 欧美日韩亚洲丝袜制服| 欧洲视频一区二区| 在线观看一区二区精品视频| 一本大道久久a久久综合婷婷 | 免费一级欧美片在线观看| 一区二区久久久久久| 亚洲精品久久久久久国产精华液| 欧美韩国一区二区| 国产精品入口麻豆九色| 国产精品国产三级国产普通话99 | 亚洲图片你懂的| 国产精品欧美久久久久无广告| 国产欧美一区二区三区鸳鸯浴| 精品电影一区二区| 国产视频一区在线播放| 中文字幕乱码一区二区免费| 亚洲国产精品二十页| 国产精品午夜免费| 综合久久给合久久狠狠狠97色 | 国产精品视频观看| 亚洲国产精品二十页| 中文字幕一区二区三区不卡在线 | 中文一区二区在线观看| 久久久久久麻豆| 国产精品欧美一区喷水| 亚洲日本电影在线| 亚洲h动漫在线| 精品在线观看免费| 成人一道本在线| 97se亚洲国产综合自在线| 欧美三级韩国三级日本一级| 欧美精品久久99久久在免费线| 日韩一区二区电影| 久久精品男人天堂av| 亚洲乱码中文字幕| 老司机精品视频线观看86 | 欧美日本在线视频| 精品国产乱码久久久久久老虎| 国产亚洲人成网站| 中文字幕中文字幕一区二区| 亚洲成人在线观看视频| 精一区二区三区| 91丨porny丨蝌蚪视频| 69av一区二区三区| 中文字幕人成不卡一区| 免费在线观看一区| 91福利小视频| 日本一区二区三区高清不卡| 亚洲大片精品永久免费| 国产91在线观看丝袜| 欧美一区二区三区在线视频| 日本一区二区三区久久久久久久久不| 亚洲精品第1页| 国产麻豆精品一区二区| 欧美日韩国产a| 最近日韩中文字幕| 国产一区二区视频在线| 色天天综合色天天久久| 欧美成人精品1314www| 亚洲影视资源网| 国产成人精品免费一区二区| 3d成人h动漫网站入口| 亚洲三级理论片| 懂色av一区二区三区免费观看 | 日韩一区日韩二区| 国产综合色产在线精品| 欧美日韩激情一区| 亚洲欧美日韩精品久久久久| 国产一区免费电影| 日韩免费视频一区| 欧美aⅴ一区二区三区视频| 91久久精品网| 亚洲天天做日日做天天谢日日欢 | 亚洲精品成人在线| eeuss鲁片一区二区三区| 久久精品视频在线看| 久久精品噜噜噜成人av农村| 欧美三电影在线| 中文子幕无线码一区tr| 国产成人在线观看| 欧美国产日韩a欧美在线观看| 九一久久久久久| 日韩欧美在线观看一区二区三区| 亚洲va欧美va人人爽午夜| 日本韩国欧美国产| 一区二区三区中文在线| 91成人在线免费观看| 悠悠色在线精品| 欧美日韩在线不卡| 日韩va亚洲va欧美va久久| 欧美群妇大交群中文字幕| 偷拍与自拍一区| 欧美一区二区精品久久911| 久久99热这里只有精品| 久久综合狠狠综合| 懂色av噜噜一区二区三区av| 欧美激情在线免费观看| 99久久久久久| 亚洲国产精品视频| 欧美一区二区视频免费观看| 精品一区二区免费在线观看| 中文字幕av一区二区三区高| 国产剧情一区在线| 中文字幕中文字幕中文字幕亚洲无线| 99久精品国产| 图片区小说区国产精品视频| 精品国产区一区| 成人黄色小视频在线观看| 亚洲另类色综合网站| 在线不卡欧美精品一区二区三区| 免费欧美在线视频| 国产精品每日更新在线播放网址| 在线免费观看日韩欧美| 久久精品久久综合| 国产精品欧美久久久久一区二区| 91久久精品午夜一区二区| 日日摸夜夜添夜夜添亚洲女人| 精品理论电影在线观看| 99国产精品久久久久久久久久久| 亚洲国产va精品久久久不卡综合| 亚洲精品一线二线三线| 91老师国产黑色丝袜在线| 美腿丝袜一区二区三区| 综合av第一页| 久久午夜羞羞影院免费观看| 色综合激情五月| 国产一区二区在线观看免费| 一区二区久久久久| 国产欧美一区二区三区鸳鸯浴| 91官网在线免费观看| 国产一区二区三区四区五区入口| 亚洲乱码中文字幕| 精品国产伦一区二区三区观看体验| 97精品国产97久久久久久久久久久久| 青青国产91久久久久久| 亚洲欧美韩国综合色| 欧美精品一区二| 欧美日韩精品高清| 91丝袜国产在线播放| 国产麻豆9l精品三级站| 美腿丝袜亚洲综合| 天天操天天综合网| 亚洲男人的天堂在线aⅴ视频| 26uuu色噜噜精品一区二区| 在线观看日韩av先锋影音电影院| 成人美女在线视频| 国产尤物一区二区| 精品一区二区三区在线观看 | 91小视频在线免费看| 国产精华液一区二区三区| 久久不见久久见中文字幕免费| 亚洲一区二区三区美女| 国产精品电影院|