中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C語言結構體,枚舉,聯合體如何使用

發布時間:2022-07-15 13:56:01 來源:億速云 閱讀:169 作者:iii 欄目:開發技術

本篇內容介紹了“C語言結構體,枚舉,聯合體如何使用”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

一、匿名結構體

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

匿名結構體對象s1過了這一行即銷毀。

二、結構體的自引用

1、聲明時不要自己引用自己

struct Node
{
 int data;
 struct Node next;//錯誤的,嚴禁自己引用自己
};
 
 
struct Node
{
 int data;
 struct Node* next;//正確的引用方式
};

2、結構體重命名時不能使用重命名

typedef struct
{
 int data;
 Node* next;//錯誤的,不要再重命名中使用重命名
}Node;
 
typedef struct Node
{
 int data;
 struct Node* next;//正確的
}Node;

三、結構體內存對齊規則

第一個成員在與結構體變量偏移量為0的地址處。

后續成員變量要放到各自的對齊數的倍數上。對齊數 = 編譯器默認對齊數與該成員類型大小的較小值。(vs中默認對齊數是8,gcc沒有默認對齊數)

結構體最終大小為最大對齊數的整數倍。

如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍。

1、結構體內存計算

struct S1
{
    char c1;
    int i;
    char c2;
};
int main()
{
    printf("%d\n", sizeof(struct S1));
    return 0;
}

C語言結構體,枚舉,聯合體如何使用

char c1在結構體變量的零偏移量處分配內存

int i的對齊數為4,所以跳過3個字節,在4的整數倍地址處分配內存

char c2的對齊數為1,使用下一個字節空間即可

目前已使用9字節

由于該結構體中所有成員變量中最大的成員類型大小為4字節,所以最大內存對齊數為4字節,結構體總大小為最大對齊數的整數倍。所以該結構體內存為12字節。

可以使用宏offsetof來觀察結構體成員在內存中的偏移量:

C語言結構體,枚舉,聯合體如何使用

2、結構體嵌套

struct S3//16
{
 double d;
 char c;
 int i;
};
struct S4//32
{
 char c1;
 struct S3 s3;
 double d;
};

char c1在結構體變量的零偏移量處分配內存

struct S3 s3按照其最大內存對齊數(此處為8)進行對齊

double d按照其最大內存對齊數(8)進行對齊

S4的最大內存對齊數為8,所以結構體的最終大小為32

3、通過調整結構體成員順序,壓縮內存

通過上述例子可以發現,結構體成員之間有很大的空間浪費,哪怕是擁有相同結構體成員的兩個結構體類型,其在內存中所占據的空間也不相同,所以為了空間的節省,在不影響數據結構的情況下,有目的的把字節占用小的成員變量放在一起,達到節省空間的目的。

四、存在內存對齊的原因

1. 平臺原因(移植原因)

不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特定類型的數據,否則拋出硬件異常。

2. 性能原因(空間換時間)

數據結構(尤其是棧)應該盡可能地在自然邊界上對齊。 原因在于,為了訪問未對齊的內存,處理器需要作兩次內存訪問;而對齊的內存訪問僅需要一次訪問。

五、修改默認對齊數

#pragma pack(2)//把默認對齊數改成2
struct S
{
    char c1;
    int i;
    short c2;
};
#pragma pack()//恢復默認對齊數為8
int main()
{
    printf("%d\n", sizeof(struct S));
    return 0;
}
#pragma pack(num)修改默認對齊數,該結構體的內存大小由12字節降低為8字節。

默認對齊數盡量為2的次方。

六、結構體傳參

結構體傳參要傳地址。

傳址調用優于傳值調用的原因是地址占4/8個字節。

但是傳值調用參數需要壓棧,當結構體過大時,參數壓棧的系統開銷較大。

七、位段

位段是在結構體中實現的。

位段的成員可以是 int、unsigned int、signed int或者是char類型

位段的空間增長方式為每次增長4個字節(int)或1個字節(char)

位段涉及很多不確定因素,位段是不跨平臺的,注重可移植的程序應該避免使用位段。

1、位段在內存中的存儲

1.1位段中char類型的存儲方式(vs中舍棄剩余空間)

struct S//占用3個字節
{
    char _a : 3;
    char _b : 4;
    char _c : 5;
    char _d : 4;
};
int main()
{
    printf("%d\n", sizeof(struct S));
    struct S s= { 0 };
    s._a = 10;//1010,截斷為010
    s._b = 12;//1100
    s._c = 3;//0011
    s._d = 4;//0100
    return 0;
}

C語言結構體,枚舉,聯合體如何使用

通過調用內存發現,&s中存儲的16進制數字為62 03 04,那么可以發現s在內存中的存儲方式如下圖:

C語言結構體,枚舉,聯合體如何使用

在vs環境中,char成員變量在單個字節中是倒著存儲的(有截斷先發生截斷),當該字節中剩余的比特位不足以存放下一個完整的成員變量時,會將剩余的比特位舍棄。

1.2位段中int類型的存儲方式(vs中利用剩余空間)

struct A//占4個字節
{
    int a : 2;
    int b : 3;
    int c : 4;
};
int main()
{
    struct A s = { 0 };
    s.a = 12;//1100,截斷為00
    s.b = 13;//1101,截斷為101
    s.c = 14;//1110
    return 0;
}

C語言結構體,枚舉,聯合體如何使用

通過調用內存發現,&s中存儲的16進制數字為d4 01 00 00,那么可以發現s在內存中的存儲方式如下圖:

C語言結構體,枚舉,聯合體如何使用

在vs環境中,int成員變量在單個字節中是倒著存儲的(有截斷先發生截斷),當該字節中剩余的比特位不足以存放下一個完整的成員變量時,會將繼續存儲,存不下的二進制位將存放至下一個字節的右側。

注意:位段冒號后面的數字只能小于等于類型大小(例如char a:9是錯誤的)

2、位段的跨平臺問題

1.int 位段被當成有符號數還是無符號數是不確定的。

2. 位段中最大位的數目不能確定。(16位機器最大16,32位機器最大32,寫成27,在16位機器會出問題。

3. 位段中的成員在內存中從左向右分配,還是從右向左分配標準尚未定義。

4. 當一個結構包含兩個位段,第二個位段成員比較大,無法容納于第一個位段剩余的位時,是舍棄剩余的位還是利用,這是不確定的。

八、枚舉

1、枚舉的定義

enum color
{
    RED,//枚舉常量
    BLUE,
    YELLOW
};

不賦值那么默認從0開始,后續枚舉成員的值遞增1

enum color
{
    RED=1,
    BLUE,
    YELLOW
};

只需要對第一個成員進行賦值,后續枚舉成員的值遞增1

在寫枚舉成員的時候建議全大寫,博主在寫通訊錄枚舉了exit,使用時vs提示該命名和exit函數沖突。

2、枚舉的優點

增加代碼的可讀性和可維護性

枚舉使用時有類型檢查,#define定義的標識符沒有

防止了命名污染(封裝)

便于調試(#define定義宏在預處理時是直接替換)

使用方便,一次可以定義多個常量

九、聯合體(共用體)

聯合也是一種特殊的自定義類型 這種類型定義的變量也包含一系列的成員,特征是這些成員共用同一塊空間(所以聯合也叫共用體)。

1、聯合體大小的計算

#include <stdio.h>
union un
{
    char arr[5];
    int a;
}u;
int main()
{
    printf("%d", sizeof(u));//8
    return 0;
}

聯合體的大小至少是最大成員的大小。

最大內存對齊數的整數倍要大于等于最大成員的大小。

(這里最大成員是arr,占5個字節,最大內存對齊數是4,所以需要為祖國聯合體開辟8個字節空間)

2、使用聯合體判斷計算機的大小端字節序

#include <stdio.h>
union un
{
    int m;
    char n;
}u;
int check_sys()
{
    u.m = 1;
    return u.n;
}
 
int main()
{
    int a = check_sys();
    if (a == 1)
        printf("小端存儲\n");
    else
        printf("大端存儲\n");
    return 0;
}

“C語言結構體,枚舉,聯合體如何使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

博客| 龙山县| 铜川市| 静宁县| 德清县| 云梦县| 红河县| 敦煌市| 乌海市| 上饶县| 雷山县| 宝应县| 新晃| 昌江| 仁寿县| 红桥区| 崇仁县| 英吉沙县| 措美县| 云阳县| 大名县| 霍邱县| 武定县| 建宁县| 合肥市| 东至县| 揭东县| 印江| 若羌县| 宣武区| 和平区| 和顺县| 迁西县| 定远县| 襄汾县| 红桥区| 交城县| 云南省| 宁乡县| 海城市| 祁东县|