欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

解析C語言中結(jié)構(gòu)體struct的對齊問題

 更新時(shí)間:2016年04月20日 11:12:18   投稿:goldensun  
這篇文章主要介紹了C語言中結(jié)構(gòu)體struct的對齊問題,作者深入到內(nèi)存分配方面來進(jìn)行解析,需要的朋友可以參考下

首先看一下結(jié)構(gòu)體對齊的三個(gè)概念值:

數(shù)據(jù)類型的默認(rèn)對齊值(自身對齊):
1.基本數(shù)據(jù)類型:為指定平臺上基本類型的長度。如在32位機(jī)器中,char對齊值為1,short為2,int,float為4,double為8;
結(jié)構(gòu)體:其數(shù)據(jù)成員中默認(rèn)對齊值最大的那個(gè)值。
2.指定對齊值:#pragma pack (value)時(shí)的指定對齊值value。
3.數(shù)據(jù)類型的有效對齊值:默認(rèn)對齊值和指定對齊值中小的那個(gè)值。
有了這些值,我們就可以很方便的來討論具體數(shù)據(jù)結(jié)構(gòu)的成員和其自身的對齊方式。有效對齊值N是最終用來決定數(shù)據(jù)存放地址方式的值,最重要。有效對齊N,就是表示“對齊在N上”,也就是說該數(shù)據(jù)的“偏移量%N=0”。而數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù)變量都是按定義的先后順序來排放的。第一個(gè)數(shù)據(jù)變量的起始地址就是數(shù)據(jù)結(jié)構(gòu)的起始地址。結(jié)構(gòu)體的成員變量要對齊排放(對于非對齊成員需要在其前面填充一些字節(jié),保證其在對齊位置上),結(jié)構(gòu)體本身也要根據(jù)自身的有效對齊值圓整(就是結(jié)構(gòu)體總長度需要是結(jié)構(gòu)體有效對齊值的整數(shù)倍)。

通過上面的分析,對結(jié)構(gòu)體進(jìn)行字節(jié)對齊,我們需要知道四個(gè)值:

  • 指定對齊值:代碼中指定的對齊值,記為packLen;
  • 默認(rèn)對齊值:結(jié)構(gòu)體中每個(gè)數(shù)據(jù)成員及結(jié)構(gòu)體本身都有默認(rèn)對齊值,記為defaultLen;
  • 成員偏移量:即相對于結(jié)構(gòu)體起始位置的長度,記為offset;
  • 成員長度:結(jié)構(gòu)體中每個(gè)數(shù)據(jù)成員的長度(注結(jié)構(gòu)體成員為補(bǔ)齊之后的長度),記為memberLen。

及兩個(gè)規(guī)則:

1.對齊規(guī)則:
offset % vaildLen = 0,其中vaildLen為有效對齊值vaildLen = min(packLen, defaultLen);

2.填充規(guī)則:
如成員變量不遵守對齊規(guī)則,則需要對其補(bǔ)齊;在其前面填充一些字節(jié)保證該成員對齊。需填充的字節(jié)數(shù)記為padLen:

padLen = getPadLen(offset , defaultLen);
int getPadLen(int offsetLen, int defaultLen)
{
  int vaildLen = min(packLen,defaultLen);
  if(0 == vaildLen || 0 == offsetLen % vaildLen)
  {
    return 0;
  }
  return vaildLen - (offsetLen % vaildLen);
}

結(jié)構(gòu)體對齊算法思想:深度優(yōu)先填充

先對齊內(nèi)層結(jié)構(gòu)體;
對每個(gè)數(shù)據(jù)成員計(jì)算其defaultLen、memberLen和offset;

再遍歷每個(gè)數(shù)據(jù)成員時(shí)計(jì)算;
對于基本數(shù)據(jù)類型成員defaultLen=memberLen;對于結(jié)構(gòu)體成員defaultLen等于它的所有成員的最大的memberLen;
遍歷時(shí)對成員的memberLen進(jìn)行累加,得到當(dāng)前成員的offsetLen;
運(yùn)用對齊及填充規(guī)則:在當(dāng)前結(jié)構(gòu)體成員前填充padLen個(gè)字節(jié);


舉例說明:

struct{

 short a;

 short b;

 short c; }A; sizeof(A) = 6; 

(vc6與gcc相同)

struct{

 long a;

 short c; }A; sizeof(A) = 8;

(vc6與gcc相同), 它的內(nèi)存分配為: a1 a2 a3 a4 , c1 c2 x x(a1為a的第一個(gè)字節(jié),x為補(bǔ)齊字節(jié),下同)

struct{

int a;

char b;

short c; }A;

sizeof(A) = 8;

A的內(nèi)存分配為:

 a1 a2 a3 a4, b1 x c1 c2
struct{

char a;

int b;

short c; }A1;

sizeof(A1) = 12;

(vc6與gcc相同)

A1的內(nèi)存分配為:

a1 x x x, b1 b2 b3 b4, c1 c2 x x

下面是更復(fù)雜的情況,結(jié)構(gòu)體作為成員

struct{

int a;

doubl b;

short c; }A; // sizeof(A) = 24 (vc6與gcc相同)

struct{

  char a,b;

int c;

double d;

short e;

struct A h;

}B;

sizeof(B) = 48 //(vc6與gcc相同)

A的內(nèi)存分布:

a1 a2 a3 a4 x x x x, b1 b2 b3 b4 b5 b6 b7 b7, c1 c2 x x x x x x

B的內(nèi)存分布:

a1 b1 x x, c1 c2 c3 c4 , d1 d2 d3 d4 d5 d6 d7 d8, e1 e2 x x x x 

相關(guān)文章

  • C++ 實(shí)現(xiàn)L2-002 鏈表去重

    C++ 實(shí)現(xiàn)L2-002 鏈表去重

    這篇文章主要介紹了C++ 實(shí)現(xiàn)L2-002 鏈表去重,本文通過簡要的案例,解題思路講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • QT使用QML實(shí)現(xiàn)地圖繪制虛線的示例代碼

    QT使用QML實(shí)現(xiàn)地圖繪制虛線的示例代碼

    QML提供了MapPolyline用于在地圖上繪制線段,這篇文章主要為大家詳細(xì)介紹了QT如何使用QML實(shí)現(xiàn)在地圖上繪制虛線,需要的小伙伴可以參考一下
    2023-07-07
  • C語言利用數(shù)組和文件實(shí)現(xiàn)登錄注冊功能

    C語言利用數(shù)組和文件實(shí)現(xiàn)登錄注冊功能

    這篇文章主要為大家詳細(xì)介紹了C語言利用數(shù)組和文件實(shí)現(xiàn)登錄注冊功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • Qt編譯OpenCV的實(shí)現(xiàn)步驟

    Qt編譯OpenCV的實(shí)現(xiàn)步驟

    本文主要介紹了Qt編譯OpenCV的實(shí)現(xiàn)步驟,通過詳細(xì)的步驟和說明,幫助開發(fā)者在Qt環(huán)境中成功集成并編譯OpenCV,從而為各類計(jì)算機(jī)視覺項(xiàng)目提供強(qiáng)大的支持,感興趣的可以了解一下
    2024-01-01
  • 指向類成員函數(shù)的指針其實(shí)并非指針

    指向類成員函數(shù)的指針其實(shí)并非指針

    對于指向類成員的指針,必須緊記,指向類成員(非static)的指針并非指針
    2013-08-08
  • C語言深入講解之從函數(shù)棧幀角度理解return關(guān)鍵字

    C語言深入講解之從函數(shù)棧幀角度理解return關(guān)鍵字

    在C語言中,一般情況下函數(shù)的返回值是通過函數(shù)中的return語句來實(shí)現(xiàn)的,每調(diào)用一次return語句只能從函數(shù)中返回一個(gè)值,這篇文章主要給大家介紹了關(guān)于C語言從函數(shù)棧幀角度理解return關(guān)鍵字的相關(guān)資料,需要的朋友可以參考下
    2021-09-09
  • C++11中的智能指針shared_ptr、weak_ptr源碼解析

    C++11中的智能指針shared_ptr、weak_ptr源碼解析

    本文是基于gcc-4.9.0的源代碼進(jìn)行分析,shared_ptr和weak_ptr是C++11才加入標(biāo)準(zhǔn)的,僅對C++智能指針shared_ptr、weak_ptr源碼進(jìn)行解析,需要讀者有一定的C++基礎(chǔ)并且對智能指針有所了解
    2021-09-09
  • c語言 兩字符串交叉合并實(shí)例

    c語言 兩字符串交叉合并實(shí)例

    今天小編就為大家分享一篇c語言 兩字符串交叉合并實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • 使用設(shè)計(jì)模式中的單例模式來實(shí)現(xiàn)C++的boost庫

    使用設(shè)計(jì)模式中的單例模式來實(shí)現(xiàn)C++的boost庫

    這篇文章主要介紹了使用設(shè)計(jì)模式中的單例模式來實(shí)現(xiàn)C++的boost庫的方法,其中作者對線程安全格外強(qiáng)調(diào),需要的朋友可以參考下
    2016-03-03
  • windows 下C++生成Dump調(diào)試文件與分析

    windows 下C++生成Dump調(diào)試文件與分析

    dump文件是C++程序發(fā)生異常時(shí),保存當(dāng)時(shí)程序運(yùn)行狀態(tài)的文件,是調(diào)試異常程序重要的方法,所以程序崩潰時(shí),除了日志文件,dump文件便成了我們查找錯(cuò)誤的最后一根救命的稻草,這篇文章主要介紹了windows 下C++生成Dump調(diào)試文件與分析,需要的朋友可以參考下
    2023-04-04

最新評論