1. 程式人生 > >結構體的詳解

結構體的詳解

結構體的初始化

結構體:為了解決C語言中基本資料型別單一的問題而應運而生的一種組合型別的資料,可以有基本型別的操作,解決了C語言不能處理複雜資料型別的問題。

結構體的定義:

    struct s
    {
        int a;
        int b[20];
        char c;
        char *d;
        ......
        可以無限的疊加,只要是實際需要或者內心需要。
    };//結構體的定義,struct為關鍵字,關鍵字之後為使用者定義的結構體的名稱,在結構體對的最末尾,必須新增結構體定義的結束標誌(;)分號。

結構體的成員變數的訪問。
定義一個結構體

struct s
{
    int a;
    char b;
}s = {4,'a'};//定義結構體的同時,定義了一個結構體的變數,之後,對這個結構體變數進行賦值。

/*可以直接訪問結構體的各個成員變數,也可以使用指標來間接的指向結構體的各成員變數。
直接訪問時,通過結構體的運算子號(.)來訪問。
例如: s.a表示結構體的a成員。s.b表示結構體的b成員。
指標訪問時,通過各個成員不同的的指標型別來訪問。
int *a1 = (int *)((long)&s); 表示結構體的a成員,a成員的型別為int型,所以採用指標型別來表示。因為64位環境下地址為8位的資料型別,所以採用long(long為8位)來強制型別轉換,最後通過每一個元素在結構體中的偏移量來計算每一個元素的值的型別。最後遍歷指標,指向最後的值。*/

對應的除了普通的結構體變數,結構體還有指標,結構體指標。當結構體指標指向了一個具體的結構體的時候,結構體指標如何呼叫指標所指向的變數。於是我們引入了一個新的運算子(->)引用時對應的
例如 :
s->a//表示結構體指標訪問結構體指標所指結構體的成員a
結構體指標更多的應用於對於結構體操作的函式之中,因為結構體的成員不定,一味地用賦值的方法,會造成記憶體的過多的浪費,及其他的記憶體浪費的現象。所以指標的出現,極大地省了記憶體的使用。

結構體的對齊。

對齊規則,使用者定義一個結構體的變數之後,編譯器會對結構體整體進行一次掃描,掃描之後,編譯器找到了一個結構體成員變數,該基礎成員變數佔用的位元組數最多,以該位元組數為該結構體的對齊位元組數。下面來一個例子。

struct data
{
    char a;
    short b;
    int c;
    long d;
};
/*
該結構體,long是佔用位元組數最多的一個基礎型別,為8位元組。
char 型別佔用了一個位元組,之後放short,編譯器發現前面的4個位元組只剩下了3個位元組,但是前面的char只用了一個位元組,但是short不會從char之後直接儲存,而是在char佔用的一個位元組之後再來一個空的位元組佔用,short再放入空間中,此時從char開始的4個位元組全部佔用完,int進來之後,發現前面對的元素佔用了4位元組(int型別的大小)的整數倍,int就直接放在了第五個位元組的地方。int 佔用了空間之後,long又來了,long發現前面的佔用了8位元組的整數倍(long型別佔用空間的整數倍),所以long也直接放在了int的後邊。該結構體佔用了16位元組額大小。最後一步,結構體各 成員變數佔用完之後,如果沒有佔用最大基礎型別的整數倍,補齊到整數倍,否則,直接完成結構體佔用記憶體處理的操作*/
/*
    先掃描,找最大佔用位元組的型別。
    第一個隨便放。
    後放的每一個依次看前一個數據型別放完之後所佔用的空間是否是自己的整數倍,是的話直接放。不是的話,補齊時候再放。
    所有成員放完之後。看佔用記憶體呢是否為,最大佔用位元組的型別的整數倍,是的話,計算完成,否則,補齊到整數倍的最小值。
*/

結構體的對齊指令

#pragma pack(n) (1、2、4、8、.....)
#pragma pack()
聯合使用,來獲得空間上的節省,但是計算機的執行效率會減少。
而且n的數值只能為2的n次方
特殊的是,當對齊指令中的n超過了結構體掃描獲得的的最大位元組型別。按照最大細節型別的對齊規則對齊。否則,按照n的對齊規則來對齊。
就是兩者取小的數值來制定對齊規則

位欄位

為欄位只用於結構體,而且結構體的各個成員必須是整形,或者是無符號整形。

struct data1
{
        unsigned a : 1;     // 1就是一個bit,範圍:0~1
        int : 31;           // 無名欄位,不可訪問,只是佔位
        unsigned b : 2;     // 2就是er個bit,範圍:0~3
        unsigned c : 2;     // 28位 
}s1;

struct data2
{
        unsigned a : 1;     // 1就是一個bit,範圍:0~1
        int : 0;            // 0欄位,不可訪問,只是佔位整個字剩下的位,全部寫0
        unsigned b : 30;    // 2就是er個bit,範圍:0~3
        int : 0;
        unsigned c : 2;     // 28位 
}s2;

//位欄位:下一個欄位不夠在剩餘的bit存放時,必須另起一個字。欄位不能跨字。
struct data3
{
        int a : 2;
        int b : 32;
}s3;
位欄位的對齊規則。
第一個先放,第二個放的時候判斷剩餘空間(4位元組中第一個佔用之後剩餘的空間)是否可以存放第二個,是就存放,否則重新開闢四位元組的空間來存放第二個資料,以此類推,直至所有成員存放結束。使用位欄位表述資料時,如果超過了某個欄位所能表述數的範圍的話,結果不可預料的。