一般的, 內(nèi)存布局我們是不需要關(guān)心的, 因為我們直接通過字段或?qū)傩詠碓L問結(jié)構(gòu)體, 但是與非托管庫操作的時候, 有時候就需要注意結(jié)構(gòu)體布局了, 只有保證布局一致, 才能保證直接傳結(jié)構(gòu)體指針時, 非托管代碼能正常訪問到成員.
成都網(wǎng)站設計、網(wǎng)站制作、外貿(mào)營銷網(wǎng)站建設介紹好的網(wǎng)站是理念、設計和技術(shù)的結(jié)合。創(chuàng)新互聯(lián)建站擁有的網(wǎng)站設計理念、多方位的設計風格、經(jīng)驗豐富的設計團隊。提供PC端+手機端網(wǎng)站建設,用營銷思維進行網(wǎng)站設計、采用先進技術(shù)開源代碼、注重用戶體驗與SEO基礎,將技術(shù)與創(chuàng)意整合到網(wǎng)站之中,以契合客戶的方式做到創(chuàng)意性的視覺化效果。[StructLayout(LayoutKind.Sequential)] // 聲明 StructLayout
struct MyStruct
{}
序列布局 (Sequential)順序布局就是按照你在結(jié)構(gòu)體中聲明成員的順序, 一個個將它們放到內(nèi)存中, 不過需要注意的是, 這些成員不是一個個緊挨著的, 他們可能存在內(nèi)存對齊, 不過這個我們下面會詳細講到.
顯式布局 (Explicit)在這種布局中, 你需要指定結(jié)構(gòu)體中每一個字段在這個結(jié)構(gòu)體中的偏移量, 例如你有一個結(jié)構(gòu)體, 它里面有兩個 int, 你希望這兩個 int 之間隔開 2 字節(jié)的大小, 那么只需要為第一個結(jié)構(gòu)體指定偏移量為 0, 第二個結(jié)構(gòu)體偏移量為 6 即可.
自動布局 (Auto)在這種布局中, 你不應該進行與非托管的互操作, 因為為了性能, 結(jié)構(gòu)體中的成員順序會被自動調(diào)整. 例如下面這個明顯沒辦法在不調(diào)整順序與不添加間隔的情況下做到內(nèi)存對齊的結(jié)構(gòu)體, 它的成員順序, 會被調(diào)整.
[StructLayout(LayoutKind.Auto)]
struct SomeIntegers
{byte AByte;
short AShortInteger;
byte AnotherByte;
// 你實際得到的可能是 byte, byte, short 這樣的一個結(jié)構(gòu)體
}
內(nèi)存對齊當你使用序列布局的時候, 結(jié)構(gòu)體成員會有內(nèi)存對齊現(xiàn)象, 而在進行內(nèi)存對齊時, 會有以下行為:
包就是內(nèi)存對齊的要求大小, 例如在 Windows 中默認是 8 字節(jié)對齊, 像是一些大于八字節(jié)的數(shù)據(jù), 按照 8 字節(jié)在內(nèi)存中進行對齊即可.
偏移量要求舉個例子, 如果我們有一個 int(32位), 那么它的內(nèi)存偏移量應該是 4, 8, 12 等這些能夠被 4 整除的值, 同理, long(64位) 的偏移量也應該是 8, 16, 32 這些.
舉個例子, 下面這個結(jié)構(gòu)體中, 成員 B 為了實現(xiàn)偏移量為 2, 在成員 A 后產(chǎn)生了 1 字節(jié)的空隙.
[StructLayout(LayoutKind.Sequential)]
struct SomeIntegers
{byte A; // 1 byte
// 1 byte
short B; // 2 bytes
}
成員占用大于包舉個例子, 在使用 8 字節(jié)的包大小時, 且在一個包內(nèi), 已經(jīng)被使用了 4 字節(jié), 如果你要裝下一個 long(8字節(jié)), 那么顯然這個包已經(jīng)裝不下這個字段了, 那么這個字段會放到下一個包.
舉個例子, 下面這個結(jié)構(gòu)體中, 成員 B 為了做到 8 字節(jié)的對齊, 它與第一個成員之間, 產(chǎn)生了 4 字節(jié)的空隙.
[StructLayout(LayoutKind.Sequential)]
struct SomeIntegers
{int A; // 4 bytes
// 4 bytes
long B; // 8 bytes
}
但是當你指定 Pack 為 4 時, 這個 long 則不再要求偏移量能被 8 整除, 而是被 4 整除即可.
[StructLayout(LayoutKind.Sequential, Pack = 4)]
struct SomeIntegers
{int A; // 4 bytes
long B; // 8 bytes (B 與 A 之間的空隙沒有了)
}
因此, 當你不希望這個結(jié)構(gòu)體產(chǎn)生任何空隙, 或者不希望這個結(jié)構(gòu)體有內(nèi)存對齊時, 指定 Pack = 1 就可以解決問題. 因為這樣會導致所有字段的偏移量能被 1 整除即可, 于是他們對于偏移量, 就沒有了任何要求.
成員尾部留空一個結(jié)構(gòu)體尾部也會產(chǎn)生一些空余的, 不被使用的字節(jié), 這個字節(jié)大小取決于結(jié)構(gòu)體中大的成員大小.
例如我一個結(jié)構(gòu)體中, 有一個long
, 有一個byte
, 大成員大小為 8, 所以結(jié)構(gòu)體的大小一定是 8 的倍數(shù).
[StructLayout(LayoutKind.Sequential)]
struct TwoIntegers // 大小共計 16 bytes
{long A; // 8 bytes
byte B; // 1 byte
// 7 bytes
}
當結(jié)構(gòu)體嵌套例如我一個結(jié)構(gòu)體中包含另外一個結(jié)構(gòu)體, 那么此時, 內(nèi)存如何對齊呢?
例如一個結(jié)構(gòu)體中, 有一個int
字段以及一個byte
字段, 它的大對其大小是 4, 也就是說, 這個結(jié)構(gòu)體在作為其他結(jié)構(gòu)體的成員時, 也會使用 4 作為對齊大小.
[StructLayout(LayoutKind.Sequential)]
struct SomeIntegers
{public byte A; // 1 byte
// 3 bytes (結(jié)構(gòu)體大對齊是 4, 所以這里留出了 4 - 1 = 3 個字節(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)體成員尾部的留空能夠裝下下一個成員, 它也不會這樣做. “結(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 (盡管上一個結(jié)構(gòu)體字段后有留空, 但這段留空不會被重復利用)
// 3 bytes (所有成員的大大小是 4, soyi這里留
}
[StructLayout(LayoutKind.Sequential)]
struct TwoIntegers
{int A; // 4 bytes
byte B; // 1 byte
// 3 bytes
}
實現(xiàn)聯(lián)合體C++ 中有聯(lián)合體這個東西, 實現(xiàn)多個字段共用一些數(shù)據(jù), 在 C# 中, 如果你要實現(xiàn)這個, 使用顯式布局即可.
舉個例子, 在下面這個 C++ 定義的結(jié)構(gòu)體中, 存在兩個字段 A 和 B, 他們共用相同的內(nèi)存區(qū)域.
struct SomeIntegers
{union {int A;
int B;
};
};
在 C# 中實現(xiàn)這個, 你可以使用:
[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# 進行編寫:
[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)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)頁題目:[.NET]結(jié)構(gòu)體布局詳解與結(jié)構(gòu)體內(nèi)存對齊具體方式-創(chuàng)新互聯(lián)
網(wǎng)站路徑:http://muchs.cn/article26/dpcojg.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供建站公司、外貿(mào)網(wǎng)站建設、Google、企業(yè)網(wǎng)站制作、外貿(mào)建站、云服務器
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容