三、結(jié)構(gòu)體(Struct)/聯(lián)合體(Union)/位域

對象的創(chuàng)建核心有三步:

接下來將對isaisa關(guān)聯(lián)類進(jìn)行解析, 在講解之前先了解下結(jié)構(gòu)體(Struct)、聯(lián)合體(Union)位域, 下篇進(jìn)入isa與類關(guān)聯(lián)四、isa與類關(guān)聯(lián)的原理

結(jié)構(gòu)體(Struct)

結(jié)構(gòu)體是C語言中一種重要的數(shù)據(jù)類型,該數(shù)據(jù)類型由一組稱為成員(或稱為域,或稱為元素)的不同數(shù)據(jù)組成,其中每個成員可以具有不同的類型。結(jié)構(gòu)體通常用來表示類型不同但是又相關(guān)的若干數(shù)據(jù)。

結(jié)構(gòu)體類型不是由系統(tǒng)定義好的,而是需要程序設(shè)計者自己定義的。C語言提供了關(guān)鍵字struct來標(biāo)識所定義的結(jié)構(gòu)體類型。

關(guān)鍵字struct結(jié)構(gòu)體名組合成一種類型標(biāo)識符,其地位如同通常的intchar等類型標(biāo)識符,其用途就像 int 類型標(biāo)識符標(biāo)識整型變量一樣可以用來定義結(jié)構(gòu)體變量。定義變量以后,該變量就可以像定義的其他變量一樣使用了;
成員又稱為成員變量,它是結(jié)構(gòu)體所包含的若干個基本的結(jié)構(gòu)類型,必須用“{}”括起來,并且要以分號結(jié)束,每個成員應(yīng)表明具體的數(shù)據(jù)類型。

struct LGStruct1 {
    double a;   // 8 (0-7)
    char b;     // 1 [8 1] (8)
    int c;      // 4 [9 4] 9 10 11 (12 13 14 15)
    short d;    // 2 [16 2] (16 17)
}struct1;

內(nèi)存使用符合內(nèi)存對齊原則

聯(lián)合體/共用體(Union)

聯(lián)合體(union)結(jié)構(gòu)體(struct)有一些相似之處。但兩者有本質(zhì)上的不同。在結(jié)構(gòu)體中,各成員有各自的內(nèi)存空間, 一個結(jié)構(gòu)變量的總長度是各成員長度之和。而在聯(lián)合體中,各成員共享一段內(nèi)存空間, 一個聯(lián)合變量的長度等于各成員中最長的長度。

聯(lián)合體是一個結(jié)構(gòu)

  • 它的所有成員相對于基地址的偏移量都為0;
  • 此結(jié)構(gòu)空間要大到足夠容納最"寬"的成員;
  • 其對齊方式要適合其中所有的成員;

聯(lián)合體的內(nèi)存對齊
聯(lián)合體所占空間需要滿足的條件:

  • 大小足夠容納最寬的成員;
  • 大小能被其包含的所有基本數(shù)據(jù)類型的大小所整除。
union U
{
    char s[9]; // 9
    int n;     // 4
    double d;  // 8
};

復(fù)制代碼聯(lián)合體的大小為 16。

位域

位域定義與結(jié)構(gòu)定義相仿,其形式為:

struct 位域結(jié)構(gòu)名 
{
  位域列表 
};

其中位域列表的形式為:

類型說明符 位域名: 位域長度(占多少位)

例如:

struct bs{
    int a:8;
    int b:2;
    int c:6;
}data;

說明 data 為 bs 變量,共占兩個字節(jié)。其中位域 a 占 8 位,位域 b 占 2 位,位域 c 占 6 位。
對于位域的定義尚有以下幾點說明:

int : 0表示下面出現(xiàn)的類型不能夠再往里面填充。

struct area
{
  int a:3;   
  int:0;     //告訴下面,20不能夠放到a的那塊存儲區(qū)域去了
  int c:20;
};

結(jié)構(gòu)體大小為4+4=8;如果沒有int:0,大小為4。

int : x 表示占用幾個位,占用部分不可用,但是接下來的位可繼續(xù)往上面填充。

struct area
{
  int a:3;   
  int:4;     //表示a和c中間有4位不可用。
  int c:20;
};

該結(jié)構(gòu)體大小為4。
如果int:4改為int:10,那么該結(jié)構(gòu)體大小會變?yōu)?。

位域不能跨字節(jié),位域需要跟結(jié)構(gòu)體最長類型對齊,前面的類型應(yīng)自動對齊,然后再進(jìn)行填充。

struct area1
{
  char a:6;   //向int對齊,擴(kuò)展為32位
  char b:3;
  int c:22;
};

結(jié)構(gòu)體大小 :8

struct area2
{
  char a:6;   //向int對齊,擴(kuò)展為32位
  char b:3;
  int c:21;
};

結(jié)構(gòu)體大小 :4

位域壓縮規(guī)則
  • 如果相鄰位域字段的類型相同,且其位寬之和小于這個類型的sizeof大小,則后面的字段將緊鄰前一個字段存儲,直到不能容納為止;
  • 如果相鄰位域字段的類型相同,但其位寬之和大于類型的sizeof大小,則后面的字段將從新的存儲單元開始,其偏移量為其類型大小的整數(shù)倍;
  • 如果相鄰的位域字段的類型不同,則各編譯器的具體實現(xiàn)有差異,VC6采取不壓縮方式,Dev-C++采取壓縮方式;
  • 如果位域字段之間穿插著非位域字段,則不進(jìn)行壓縮;
  • 整個結(jié)構(gòu)體的總大小為最寬基本類型成員大小的整數(shù)倍。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。