真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

[.NET]結(jié)構(gòu)體布局詳解與結(jié)構(gòu)體內(nèi)存對(duì)齊具體方式-創(chuàng)新互聯(lián)

內(nèi)存布局

一般的, 內(nèi)存布局我們是不需要關(guān)心的, 因?yàn)槲覀冎苯油ㄟ^字段或?qū)傩詠碓L問結(jié)構(gòu)體, 但是與非托管庫操作的時(shí)候, 有時(shí)候就需要注意結(jié)構(gòu)體布局了, 只有保證布局一致, 才能保證直接傳結(jié)構(gòu)體指針時(shí), 非托管代碼能正常訪問到成員.

成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、外貿(mào)營銷網(wǎng)站建設(shè)介紹好的網(wǎng)站是理念、設(shè)計(jì)和技術(shù)的結(jié)合。創(chuàng)新互聯(lián)建站擁有的網(wǎng)站設(shè)計(jì)理念、多方位的設(shè)計(jì)風(fēng)格、經(jīng)驗(yàn)豐富的設(shè)計(jì)團(tuán)隊(duì)。提供PC端+手機(jī)端網(wǎng)站建設(shè),用營銷思維進(jìn)行網(wǎng)站設(shè)計(jì)、采用先進(jìn)技術(shù)開源代碼、注重用戶體驗(yàn)與SEO基礎(chǔ),將技術(shù)與創(chuàng)意整合到網(wǎng)站之中,以契合客戶的方式做到創(chuàng)意性的視覺化效果。
[StructLayout(LayoutKind.Sequential)]    // 聲明 StructLayout 
struct MyStruct
{}
序列布局 (Sequential)

順序布局就是按照你在結(jié)構(gòu)體中聲明成員的順序, 一個(gè)個(gè)將它們放到內(nèi)存中, 不過需要注意的是, 這些成員不是一個(gè)個(gè)緊挨著的, 他們可能存在內(nèi)存對(duì)齊, 不過這個(gè)我們下面會(huì)詳細(xì)講到.

顯式布局 (Explicit)

在這種布局中, 你需要指定結(jié)構(gòu)體中每一個(gè)字段在這個(gè)結(jié)構(gòu)體中的偏移量, 例如你有一個(gè)結(jié)構(gòu)體, 它里面有兩個(gè) int, 你希望這兩個(gè) int 之間隔開 2 字節(jié)的大小, 那么只需要為第一個(gè)結(jié)構(gòu)體指定偏移量為 0, 第二個(gè)結(jié)構(gòu)體偏移量為 6 即可.

自動(dòng)布局 (Auto)

在這種布局中, 你不應(yīng)該進(jìn)行與非托管的互操作, 因?yàn)闉榱诵阅? 結(jié)構(gòu)體中的成員順序會(huì)被自動(dòng)調(diào)整. 例如下面這個(gè)明顯沒辦法在不調(diào)整順序與不添加間隔的情況下做到內(nèi)存對(duì)齊的結(jié)構(gòu)體, 它的成員順序, 會(huì)被調(diào)整.

[StructLayout(LayoutKind.Auto)]
struct SomeIntegers
{byte AByte;
    short AShortInteger;
    byte AnotherByte;

    // 你實(shí)際得到的可能是 byte, byte, short 這樣的一個(gè)結(jié)構(gòu)體
}
內(nèi)存對(duì)齊

當(dāng)你使用序列布局的時(shí)候, 結(jié)構(gòu)體成員會(huì)有內(nèi)存對(duì)齊現(xiàn)象, 而在進(jìn)行內(nèi)存對(duì)齊時(shí), 會(huì)有以下行為:

  1. 一個(gè)成員的內(nèi)存偏移量, 應(yīng)該能夠被它自身所占大小整除
  2. 如果一個(gè)成員占用內(nèi)存大于包(Pack)的大小, 那么不再要求它的偏移量能被它自身大小整除, 而是能夠被包大小整除即可.
什么是包

包就是內(nèi)存對(duì)齊的要求大小, 例如在 Windows 中默認(rèn)是 8 字節(jié)對(duì)齊, 像是一些大于八字節(jié)的數(shù)據(jù), 按照 8 字節(jié)在內(nèi)存中進(jìn)行對(duì)齊即可.

偏移量要求

舉個(gè)例子, 如果我們有一個(gè) int(32位), 那么它的內(nèi)存偏移量應(yīng)該是 4, 8, 12 等這些能夠被 4 整除的值, 同理, long(64位) 的偏移量也應(yīng)該是 8, 16, 32 這些.

舉個(gè)例子, 下面這個(gè)結(jié)構(gòu)體中, 成員 B 為了實(shí)現(xiàn)偏移量為 2, 在成員 A 后產(chǎn)生了 1 字節(jié)的空隙.

[StructLayout(LayoutKind.Sequential)]
struct SomeIntegers
{byte A;     // 1 byte
                // 1 byte
    short B;    // 2 bytes
}
成員占用大于包

舉個(gè)例子, 在使用 8 字節(jié)的包大小時(shí), 且在一個(gè)包內(nèi), 已經(jīng)被使用了 4 字節(jié), 如果你要裝下一個(gè) long(8字節(jié)), 那么顯然這個(gè)包已經(jīng)裝不下這個(gè)字段了, 那么這個(gè)字段會(huì)放到下一個(gè)包.

舉個(gè)例子, 下面這個(gè)結(jié)構(gòu)體中, 成員 B 為了做到 8 字節(jié)的對(duì)齊, 它與第一個(gè)成員之間, 產(chǎn)生了 4 字節(jié)的空隙.

[StructLayout(LayoutKind.Sequential)]
struct SomeIntegers
{int A;    // 4 bytes
              // 4 bytes
    long B;   // 8 bytes
}

但是當(dāng)你指定 Pack 為 4 時(shí), 這個(gè) long 則不再要求偏移量能被 8 整除, 而是被 4 整除即可.

[StructLayout(LayoutKind.Sequential, Pack = 4)]
struct SomeIntegers
{int A;    // 4 bytes
    long B;   // 8 bytes (B 與 A 之間的空隙沒有了)
}

因此, 當(dāng)你不希望這個(gè)結(jié)構(gòu)體產(chǎn)生任何空隙, 或者不希望這個(gè)結(jié)構(gòu)體有內(nèi)存對(duì)齊時(shí), 指定 Pack = 1 就可以解決問題. 因?yàn)檫@樣會(huì)導(dǎo)致所有字段的偏移量能被 1 整除即可, 于是他們對(duì)于偏移量, 就沒有了任何要求.

成員尾部留空

一個(gè)結(jié)構(gòu)體尾部也會(huì)產(chǎn)生一些空余的, 不被使用的字節(jié), 這個(gè)字節(jié)大小取決于結(jié)構(gòu)體中大的成員大小.

例如我一個(gè)結(jié)構(gòu)體中, 有一個(gè)long, 有一個(gè)byte, 大成員大小為 8, 所以結(jié)構(gòu)體的大小一定是 8 的倍數(shù).

[StructLayout(LayoutKind.Sequential)]
struct TwoIntegers  // 大小共計(jì) 16 bytes
{long A;  // 8 bytes
    byte B;  // 1 byte
             // 7 bytes
}
當(dāng)結(jié)構(gòu)體嵌套

例如我一個(gè)結(jié)構(gòu)體中包含另外一個(gè)結(jié)構(gòu)體, 那么此時(shí), 內(nèi)存如何對(duì)齊呢?

  1. 結(jié)構(gòu)體字段與前一個(gè)字段之間會(huì)產(chǎn)生的間隙, 取決于結(jié)構(gòu)體中大的對(duì)齊大小.
  2. 結(jié)構(gòu)體字段自身所存在的尾部留空內(nèi)存, 仍然會(huì)在外層結(jié)構(gòu)體中保留
1. 結(jié)構(gòu)體字段前的間隙

例如一個(gè)結(jié)構(gòu)體中, 有一個(gè)int字段以及一個(gè)byte字段, 它的大對(duì)其大小是 4, 也就是說, 這個(gè)結(jié)構(gòu)體在作為其他結(jié)構(gòu)體的成員時(shí), 也會(huì)使用 4 作為對(duì)齊大小.

[StructLayout(LayoutKind.Sequential)]
struct SomeIntegers
{public byte A;              // 1 byte
                                // 3 bytes (結(jié)構(gòu)體大對(duì)齊是 4, 所以這里留出了 4 - 1 = 3 個(gè)字節(jié))
    public TwoIntegers B;       // 16 bytes
    public byte C;              // 1 byte
                                // 7 bytes
}

[StructLayout(LayoutKind.Sequential)]
struct TwoIntegers
{int A;     // 4 bytes
    byte B;    // 1 
}
2. 結(jié)構(gòu)體尾部留空

即便結(jié)構(gòu)體成員尾部的留空能夠裝下下一個(gè)成員, 它也不會(huì)這樣做. “結(jié)構(gòu)體自己的內(nèi)存空間完整不可侵犯”

[StructLayout(LayoutKind.Sequential)]
struct SomeIntegers
{public byte A;              // 1 byte
                                // 3 byte
    public TwoIntegers B;       // 8 bytes
    public byte C;              // 1 byte   (盡管上一個(gè)結(jié)構(gòu)體字段后有留空, 但這段留空不會(huì)被重復(fù)利用)
                                // 3 bytes  (所有成員的大大小是 4, soyi這里留
}

[StructLayout(LayoutKind.Sequential)]
struct TwoIntegers
{int A;    // 4 bytes
    byte B;   // 1 byte
              // 3 bytes
}
實(shí)現(xiàn)聯(lián)合體

C++ 中有聯(lián)合體這個(gè)東西, 實(shí)現(xiàn)多個(gè)字段共用一些數(shù)據(jù), 在 C# 中, 如果你要實(shí)現(xiàn)這個(gè), 使用顯式布局即可.

舉個(gè)例子, 在下面這個(gè) C++ 定義的結(jié)構(gòu)體中, 存在兩個(gè)字段 A 和 B, 他們共用相同的內(nèi)存區(qū)域.

struct SomeIntegers
{union {int A;
        int B;
    };
};

在 C# 中實(shí)現(xiàn)這個(gè), 你可以使用:

[StructLayout(LayoutKind.Explicit)]
struct SomeIntegers
{[FieldOffset(0)]
    int A;

    [FieldOffset(0)]
    int B;
}

或者這樣的 C++ 結(jié)構(gòu)體:

struct SomeIntegers
{union {int A;
        struct {short Head;
            short Tail;
        };
    };
};

可以這樣用 C# 進(jìn)行編寫:

[StructLayout(LayoutKind.Explicit)]
struct SomeIntegers
{[FieldOffset(0)]
    int A;               // 占 4 字節(jié)

    [FieldOffset(0)]
    short Head;          // 占 2 字節(jié)

    [FieldOffset(2)]
    short Tail;          // 占 2 字節(jié)
}

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧


文章題目:[.NET]結(jié)構(gòu)體布局詳解與結(jié)構(gòu)體內(nèi)存對(duì)齊具體方式-創(chuàng)新互聯(lián)
網(wǎng)頁地址:http://weahome.cn/article/dpcojg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部