最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C# 中的 sizeof 與非托管類(lèi)型約束全解析

 更新時(shí)間:2026年03月30日 09:02:00   作者:MutoKazuo  
在 C# 中,sizeof 是一個(gè)用于獲取非托管類(lèi)型(Unmanaged Type)在內(nèi)存中所占字節(jié)數(shù)(Byte)的運(yùn)算符,這篇文章主要介紹了深入理解 C# 中的 sizeof 與非托管類(lèi)型約束,需要的朋友可以參考下

它的作用是在編譯時(shí)獲取非托管類(lèi)型所占用的字節(jié)數(shù)。它就像是內(nèi)存的“空間丈量尺”,告訴你這個(gè)類(lèi)型在內(nèi)存里到底占了多大的地兒。

在 C# 中,sizeof 是一個(gè)用于獲取非托管類(lèi)型(Unmanaged Type)內(nèi)存中所占字節(jié)數(shù)(Byte)的運(yùn)算符。它的本質(zhì)是編譯器指令,在編譯階段就能確定數(shù)值。

1. 它到底在查什么?

sizeof 的核心在于內(nèi)存布局(Memory Layout)。計(jì)算機(jī)存儲(chǔ)數(shù)據(jù)時(shí),不同的數(shù)據(jù)類(lèi)型需要占用不同大小的連續(xù)空間。sizeof 告訴程序:如果要為一個(gè)變量分配空間,到底需要切出多大的一塊內(nèi)存。

2. 核心語(yǔ)法與約束

sizeof 的用法非常簡(jiǎn)單,但受限于 C# 的安全機(jī)制:

  • 內(nèi)置基礎(chǔ)類(lèi)型:可以直接使用,如 sizeof(int)
  • 自定義結(jié)構(gòu)體:必須在 unsafe(不安全)上下文中使用。
  • 局限性:它不能用于引用類(lèi)型(Reference Type),如 class,因?yàn)橐妙?lèi)型的大小在堆棧上只是一個(gè)指針大小,其實(shí)際內(nèi)容在堆中分配,且受垃圾回收(GC)影響,布局不固定。

流程圖:sizeof 的執(zhí)行邏輯

3. 代碼示例

基礎(chǔ)用法

對(duì)于內(nèi)置類(lèi)型,sizeof 返回的是可預(yù)見(jiàn)的結(jié)果:

Console.WriteLine(sizeof(byte));   // 輸出: 1
Console.WriteLine(sizeof(int));    // 輸出: 4
Console.WriteLine(sizeof(long));   // 輸出: 8
Console.WriteLine(sizeof(double)); // 輸出: 8

進(jìn)階用法:自定義結(jié)構(gòu)體

當(dāng)處理自定義結(jié)構(gòu)時(shí),需要考慮內(nèi)存對(duì)齊(Memory Alignment)

using System;
struct MyStruct
{
    public byte A; // 1 byte
    public int B;  // 4 bytes
}
class Program
{
    static void Main()
    {
        // 必須開(kāi)啟 unsafe 編譯選項(xiàng)
        unsafe
        {
            // 結(jié)果是 8,而不是 5。
            // 因?yàn)榫幾g器為了 CPU 讀取效率,會(huì)對(duì)字段進(jìn)行填充(Padding)。
            Console.WriteLine($"結(jié)構(gòu)體大小: {sizeof(MyStruct)}");
        }
    }
}

4. 常用使用場(chǎng)景

  • 非托管互操作(Interop):當(dāng)你調(diào)用 C/C++ 寫(xiě)的動(dòng)態(tài)鏈接庫(kù)(DLL)時(shí),需要精確告訴系統(tǒng)你要傳遞多大的數(shù)據(jù)塊。
  • 序列化與二進(jìn)制讀寫(xiě):在高性能場(chǎng)景下,直接操作 byte[] 數(shù)組時(shí),通過(guò) sizeof 確定偏移量。
  • 內(nèi)存池分配:預(yù)先申請(qǐng)一塊內(nèi)存空間,計(jì)算總?cè)萘繒r(shí)使用。
  • 性能優(yōu)化:通過(guò) sizeof 觀察結(jié)構(gòu)體對(duì)齊情況,減少內(nèi)存碎片的浪費(fèi)。

除了基礎(chǔ)的內(nèi)存分配,在資深軟件工程師眼中,sizeof 更多用于底層優(yōu)化精密控制

A. 棧上內(nèi)存分配 (stackalloc)

在追求極致性能的場(chǎng)景(如解析高頻金融數(shù)據(jù)),我們避開(kāi)堆內(nèi)存,直接在棧上開(kāi)辟空間。

// 申請(qǐng) 100 個(gè) int 大小的??臻g
Span<int> numbers = stackalloc int[100];
// 在底層邏輯中,它等同于申請(qǐng)了 100 * sizeof(int) 字節(jié)

B. 泛型約束中的內(nèi)存計(jì)算

在 C# 7.3 之后,我們可以使用 where T : unmanaged 約束。配合 sizeof,可以編寫(xiě)極其通用的高性能代碼。

public unsafe void CopyData<T>(T* source, T* destination, int count) where T : unmanaged
{
    // 自動(dòng)根據(jù) T 的類(lèi)型計(jì)算需要復(fù)制的字節(jié)總數(shù)
    long totalBytes = (long)count * sizeof(T);
    Buffer.MemoryCopy(source, destination, totalBytes, totalBytes);
}

C. 固定內(nèi)存塊偏移 (Fixed Memory Offset)

當(dāng)你在處理復(fù)雜的二進(jìn)制協(xié)議(如網(wǎng)絡(luò)封包、視頻解碼)時(shí),sizeof 是計(jì)算偏移量的唯一準(zhǔn)繩。

sizeof(sbyte)1
sizeof(byte)1
sizeof(short)2
sizeof(ushort)2
sizeof(int)4
sizeof(uint)4
sizeof(long)8
sizeof(ulong)8
sizeof(char)2
sizeof(float)4
sizeof(double)8
sizeof(decimal)16
sizeof(bool)1

5. Marshal.SizeOf

在實(shí)際開(kāi)發(fā)中,Marshal.SizeOf 最經(jīng)典的舞臺(tái)就是 Win32 API 調(diào)用。

很多 Windows 底層的函數(shù)要求你傳入一個(gè)結(jié)構(gòu)體,并且在這個(gè)結(jié)構(gòu)體的第一個(gè)字段里,你必須明確告訴系統(tǒng):“這個(gè)結(jié)構(gòu)體本人占用了多少字節(jié)”。如果這個(gè)數(shù)字填錯(cuò)了,系統(tǒng)為了安全會(huì)直接拒絕執(zhí)行。

1. 為什么要運(yùn)行時(shí)測(cè)量?

Windows API 設(shè)計(jì)時(shí)為了向前兼容,經(jīng)常會(huì)在同一個(gè)結(jié)構(gòu)體的后續(xù)版本中增加字段。系統(tǒng)通過(guò)檢查你傳入的 Size(大?。﹣?lái)判斷你使用的是哪一個(gè)版本的結(jié)構(gòu)體,從而決定如何處理內(nèi)存。

2. 核心場(chǎng)景:獲取系統(tǒng)托盤(pán)圖標(biāo)信息

假設(shè)我們要獲取 Windows 任務(wù)欄通知區(qū)域(托盤(pán))的圖標(biāo)信息,會(huì)用到 NOTIFYICONDATA 結(jié)構(gòu)體。

using System;
using System.Runtime.InteropServices;
// 定義符合 Win32 布局的結(jié)構(gòu)體
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct NOTIFYICONDATA
{
    public int cbSize;        // 結(jié)構(gòu)體本身的大?。P(guān)鍵!)
    public IntPtr hWnd;       // 窗口句柄
    public uint uID;          // 圖標(biāo) ID
    public uint uFlags;       // 標(biāo)志位
    public uint uCallbackMessage;
    public IntPtr hIcon;      // 圖標(biāo)句柄
    // ... 其他字段省略
}
class Program
{
    static void Main()
    {
        NOTIFYICONDATA data = new NOTIFYICONDATA();
        // 場(chǎng)景:初始化結(jié)構(gòu)體時(shí),必須告知系統(tǒng)該結(jié)構(gòu)體的大小
        // 這里不能用 sizeof(NOTIFYICONDATA),因?yàn)樵跊](méi)有 unsafe 的環(huán)境下無(wú)法編譯
        // 且 Marshal.SizeOf 會(huì)考慮 CharSet 帶來(lái)的字符編碼寬度差異
        data.cbSize = Marshal.SizeOf(typeof(NOTIFYICONDATA));
        Console.WriteLine($"結(jié)構(gòu)體在托管內(nèi)存中的大小推算為: {data.cbSize} 字節(jié)");
        // 模擬調(diào)用 Win32 API
        // Shell_NotifyIcon(NIM_ADD, ref data);
    }
}

3. 為什么這個(gè)例子不用 sizeof?

  1. 無(wú)需 unsafeMarshal.SizeOf 可以在普通的托管代碼中運(yùn)行,不需要開(kāi)啟項(xiàng)目的“允許不安全代碼”開(kāi)關(guān)。
  2. 封送感知 (Marshaling Awareness)Marshal.SizeOf 會(huì)考慮 StructLayout 屬性。例如,如果結(jié)構(gòu)體里有 string,sizeof 根本無(wú)法處理,而 Marshal.SizeOf 會(huì)根據(jù)你指定的 CharSet(如 Unicode 占 2 字節(jié),Ansi 占 1 字節(jié))來(lái)計(jì)算它轉(zhuǎn)化成 C 語(yǔ)言格式后的大小。

4. 流程圖:Marshal.SizeOf 如何在運(yùn)行時(shí)工作

5. sizeof vs Marshal.SizeOf

它位于 System.Runtime.InteropServices 命名空間下。只要你安裝了 .NET SDK,就可以直接通過(guò) using 引用它。

  • 本質(zhì)區(qū)別
    • sizeof:**編譯時(shí)(Compile-time)**指令。它直接硬編碼數(shù)值到程序中,速度極快,但只能用于非托管類(lèi)型。
    • Marshal.SizeOf:運(yùn)行時(shí)(Runtime)方法。它通過(guò)反射(Reflection)去測(cè)量對(duì)象在內(nèi)存布局(特別是轉(zhuǎn)換為非托管格式后)的大小,支持 struct 實(shí)例,也能處理一些被裝箱的對(duì)象,但性能開(kāi)銷(xiāo)比 sizeof 。
特性sizeofMarshal.SizeOf
性能極高(等同于直接寫(xiě)數(shù)字)一般(有運(yùn)行時(shí)開(kāi)銷(xiāo))
上下文要求涉及自定義結(jié)構(gòu)需 unsafe無(wú)需 unsafe
靈活性只能用類(lèi)型名,不能用變量名可以直接傳入變量實(shí)例
主要目的算偏移量、算指針位移調(diào)用 Win32 API、處理復(fù)雜封送

6. 易混淆

  • 句柄 (Handle/IntPtr):可以理解為系統(tǒng)資源的“代號(hào)”或“門(mén)票”。在 64 位系統(tǒng)下,它的大小等同于 long(8 字節(jié))。
  • 封送 (Marshaling):將 C# 中的對(duì)象搬運(yùn)到內(nèi)存緩沖區(qū),并轉(zhuǎn)換成 C/C++ 能看懂的格式的過(guò)程。
  • StructLayout (LayoutKind.Sequential):強(qiáng)制要求編譯器按照你在代碼里寫(xiě)字段的順序來(lái)排列內(nèi)存,不要為了優(yōu)化而打亂順序,否則 Windows 系統(tǒng)會(huì)讀錯(cuò)數(shù)據(jù)。
  • 非托管類(lèi)型 (Unmanaged Type):指不需要垃圾回收器(GC)管理的類(lèi)型。包括 sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, 枚舉, 以及只包含這些類(lèi)型的結(jié)構(gòu)體。
  • 內(nèi)存對(duì)齊 (Memory Alignment):CPU 讀取內(nèi)存時(shí)不是一個(gè)字節(jié)一個(gè)字節(jié)讀的,而是以“塊”(如 4 或 8 字節(jié))為單位。為了提高讀取速度,編譯器會(huì)在數(shù)據(jù)結(jié)構(gòu)之間插入一些無(wú)用的空字節(jié),使數(shù)據(jù)起始地址落在塊的邊界上。
  • 填充 (Padding):內(nèi)存對(duì)齊過(guò)程中自動(dòng)添加的空閑字節(jié)。
  • unsafe 上下文:C# 默認(rèn)是內(nèi)存安全的,不允許直接操作地址。通過(guò) unsafe 關(guān)鍵字,你可以在特定區(qū)域內(nèi)像 C 語(yǔ)言一樣直接操作指針和查看原始內(nèi)存布局。

到此這篇關(guān)于C# 中的 sizeof 與非托管類(lèi)型約束全解析的文章就介紹到這了,更多相關(guān)C# sizeof 與非托管類(lèi)型約束內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c# 圓形識(shí)別方案和直線(xiàn)識(shí)別方案的參考示例

    c# 圓形識(shí)別方案和直線(xiàn)識(shí)別方案的參考示例

    這篇文章主要介紹了c# 圓形識(shí)別方案和直線(xiàn)識(shí)別方案的實(shí)現(xiàn)示例,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-03-03
  • C#基于Miniblink控件編寫(xiě)一個(gè)簡(jiǎn)易的瀏覽器

    C#基于Miniblink控件編寫(xiě)一個(gè)簡(jiǎn)易的瀏覽器

    miniblink是一款精簡(jiǎn)小巧的瀏覽器控件,基于chromium精簡(jiǎn)而成,是市面上最小巧的chromium內(nèi)核控件沒(méi)有之一,本文將結(jié)合C#和Miniblink編寫(xiě)一個(gè)簡(jiǎn)易的瀏覽器,感興趣的可以了解下
    2024-01-01
  • C# Email郵件發(fā)送功能 找回或重置密碼功能

    C# Email郵件發(fā)送功能 找回或重置密碼功能

    這篇文章主要為大家詳細(xì)介紹了C# Email郵件發(fā)送功能,找回或重置密碼功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • C#使用Linq to XML進(jìn)行XPath查詢(xún)的代碼實(shí)現(xiàn)

    C#使用Linq to XML進(jìn)行XPath查詢(xún)的代碼實(shí)現(xiàn)

    最近在用到HtmlAgliltyPack進(jìn)行結(jié)點(diǎn)查詢(xún)時(shí),發(fā)現(xiàn)這里選擇結(jié)點(diǎn)使用的是XPath,所以這里總結(jié)一下在C#中使用XPath查詢(xún)XML的方法,習(xí)慣了用Linq,這里也是用的Linq to xml的,需要的朋友可以參考下
    2024-08-08
  • 在C# .NET Core中繪制Chart圖表并導(dǎo)出到PDF的實(shí)現(xiàn)方法

    在C# .NET Core中繪制Chart圖表并導(dǎo)出到PDF的實(shí)現(xiàn)方法

    正好最近的項(xiàng)目需要在后端繪制Chart圖標(biāo)并進(jìn)行導(dǎo)出,查閱相關(guān)資料后想著記錄以下,本文將詳細(xì)介紹在.NET Core環(huán)境中如何繪制Chart圖表并將其導(dǎo)出到PDF文檔中,并分析這種實(shí)現(xiàn)方式的技術(shù)價(jià)值和應(yīng)用場(chǎng)景,需要的朋友可以參考下
    2025-10-10
  • C#如何利用反射將枚舉綁定到下拉框詳解

    C#如何利用反射將枚舉綁定到下拉框詳解

    這篇文章主要給大家介紹了關(guān)于C#如何利用反射將枚舉綁定到下拉框的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧
    2018-07-07
  • C#使用OpenCvSharp實(shí)現(xiàn)透視變換功能

    C#使用OpenCvSharp實(shí)現(xiàn)透視變換功能

    這篇文章主要為大家詳細(xì)介紹了C#如何使用OpenCvSharp實(shí)現(xiàn)透視變換的功能,文中的示例代碼簡(jiǎn)潔易懂,具有一定的學(xué)習(xí)價(jià)值,需要的小伙伴可以參考下
    2023-11-11
  • C#判斷字符串不等于空的方法小結(jié)

    C#判斷字符串不等于空的方法小結(jié)

    在C#中,要判斷一個(gè)字符串是否不等于空(即它既不是null也不是空字符串""),方法有如下幾種,文中通過(guò)代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-06-06
  • C#8.0新語(yǔ)法using?declaration

    C#8.0新語(yǔ)法using?declaration

    這篇文章介紹了C#8.0的新語(yǔ)法using?declaration,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • C#簡(jiǎn)單實(shí)現(xiàn)在網(wǎng)頁(yè)上發(fā)郵件的案例

    C#簡(jiǎn)單實(shí)現(xiàn)在網(wǎng)頁(yè)上發(fā)郵件的案例

    本文分享一個(gè)C#利用SMTP發(fā)送郵件的案例,提供了前后臺(tái)代碼,方便大家學(xué)習(xí)。
    2016-03-03

最新評(píng)論

聊城市| 栾城县| 吴旗县| 永安市| 乌审旗| 彝良县| 梓潼县| 宁乡县| 滨州市| 青龙| 西和县| 且末县| 银川市| 永川市| 海安县| 平塘县| 昭苏县| 平湖市| 蒙阴县| 乌拉特中旗| 永吉县| 曲阜市| 彭水| 农安县| 原阳县| 巍山| 明星| 巴里| 兰溪市| 资阳市| 广灵县| 梨树县| 扎赉特旗| 苏尼特右旗| 疏勒县| 明水县| 高邑县| 曲松县| 万荣县| 来宾市| 安多县|