結構體、位段、枚舉、聯合

結構體,是一個包含不同類型元素的集合。它和數組很像,數組是相同類型元素的集合。

1.結構體的聲明
例如描述一個學生:

struct stu
{
    char name[20];
    int age;
    char sex[3];
    char id[20];
};//分號不能丟

特殊的聲明:
在聲明結構的時候,可以不完全聲明。

struct
{
    int a;
    char b;
    float c;
}x;
struct
{
    int a;
    char b;
    float c;
}a[20],*p;

上面兩個結構體在聲明的時候都省略掉了結構體標籤。
而且,上面兩個結構體看起來名字相同,但是,編譯器會把上面兩個聲明當成兩個完全不同的類型。
還有,結構的成員可以是標量、數組、指針,甚至是其他的結構體。

當結構體的成員是本身結構體時,我們把這種情況叫做結構體的自引用。

struct node
{
    int data;
    struct node* next;
};

訪問結構體成員有兩種方式:
比如:

struct stu
{
    char name[20];
    int age;
};

方式1:stu.name
方式2:stu->age

2.結構體變量的定義

struct P
{
    int x;
    double y;
}p1;//聲明類型的同時定義變量p1
struct P p2;//定義結構體變量p2

需要注意的是,結構體內的元素必須大於等於1個,也就是說,結構體內不能不放元素,至少要有一個元素。

3.結構體內存對齊
對齊規則:

1.第一個成員在與結構體變量偏移量爲0的地址處。
2.其他成員變量要對齊到對齊數的整數倍的地址處。
  對齊數:編譯器默認的一個對齊數與該成員大小的較小值。
  **vs中默認的值爲8
  Linux中默認的值爲4**
3.結構體的總大小爲最大對齊數的整數倍。
4.如果嵌套了結構體的情況,嵌套的結構體對齊到自己最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數的整數倍。

爲什麼要內存對齊?
主要有兩個原因:

1.平臺原因:
不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特定類型的數據,否則拋出硬件異常。
2.性能原因
數據結構(尤其是棧)應該儘可能在自然邊界上對齊。原因在於,爲了訪問未對齊的內存,處理器需要作兩次訪問;而對齊的內存僅需要訪問一次。

總的來說:
結構體的內存對齊是拿空間來換時間的做法。

4.位段

位段和結構體是類似的,有兩個不同:

1.位段的成員必須是intunsigned intsigned int2.位段的成員名後面有一個冒號和一個數字。

比如:

struct A
{
    int _a:2;
    int _b:5;
    int _c:10;
    int _d:30;
};

A就是一個位段類型。

位段的內存分配

1.位段的成員可以是intunsigned intsigned int或者是char類型。
2.位段的空間上是按照需要以4個字節(int)或者1個字節(char)的方式來開闢的。
3.位段涉及很多不確定因素,位段是不跨平臺的,注意可移植的程序一個避免使用位段。

5.枚舉
枚舉,顧名思義就是一一列舉。
枚舉定義:

enum color
{
    red,
    green,
    blue,
}

枚舉的優點

1.增強代碼的可讀性和可維護性
2.#define定義的標識符比較,枚舉有類型檢查,更加嚴謹。
3.防止了命名污染
4.便於調試
5.使用方便,一次可以定義多個變量

6.聯合
聯合體的特徵就是,聯合體內的成員共用一塊內存空間,所以聯合體也叫共用體。
聯合體聲明

union Un
{
    char c;
    int i;
};

聯合體變量的定義

union Un un;

聯合的特點

聯合體共用一塊內存空間,這樣一個聯合變量的大小,至少是最大成員的大小。
當聯合體最大成員的大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章