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

溫馨提示×

溫馨提示×

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

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

自定義類型:結構體+枚舉+聯合

發布時間:2020-07-22 18:59:16 來源:網絡 閱讀:519 作者:wx5c863047de0a5 欄目:編程語言

自定義類型:結構體,枚舉,聯合
一、結構體
1.結構體的聲明
struct Stu
{
char name[20]; //名字
int age; //年齡
char sex[5]; //性別
char id[20]; //學號
}; //分號不能丟
注:
(1)C語言中結構體成員不能為空,C++中可以;
(2)沒有名字的結構體稱為“匿名結構體”,不建議出現這樣的結構體;
(3)有幾個結構體聲明就有幾種結構體類型,即使成員一模一樣,兩個結構體仍然不同。
2.結構體的自引用
直接在結構體中嵌套自身結構體作為成員在某些操作時無異于“死循環”,例如sizeof(結構體),將無法運算。正確的自引用是用自身結構體指針作為結構體成員,如下:
(1)struct Node
{
int data;
struct Node next;
};
(2)typedef struct Node
{
int data;
struct Node
next;
}Node;

3.結構體變量的定義和初始化
struct Point
{
int x;
int y;
}p1; //聲明類型的同時定義變量p1
struct Point p2; //定義結構體變量p2

//初始化:定義變量的同時賦初值。
struct Point p3 = {x, y};
struct Stu ? ? ? ?//類型聲明
{
char name[15];//名字
int age; ? ? ?//年齡
};
struct Stu s = {"zhangsan", 20};//初始化
注:結構體和數組一樣,可以整體初始化,但不能整體賦值!

struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {10,{4,5},NULL}; //結構體嵌套初始化
struct Node n2 = {20, {5, 6}, NULL}; //結構體嵌套初始化

4.結構體內存對齊
對齊:待放入變量的起始偏移量能整除對齊數就稱為“對齊”。
注:編譯器沒有默認對齊數

(1)為什么存在內存對齊?
大部分的參考資料都是如是說的:
①平臺原因(移植原因): 不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特定類型的數據,否則拋出硬件異常。
②性能原因: 數據結構(尤其是棧)應該盡可能地在自然邊界上對齊。 原因在于,為了訪問未對齊的內存,處理器需要作兩次內存訪問;而對齊的內存訪問僅需要一次訪問。

(2)結構體的對齊規則:
<1>第一個成員在與結構體變量偏移量為0的地址處。
<2>其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處。
<3>結構體總大小為最大對齊數(每個成員變量都有一個對齊數)的整數倍。
<4>如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍。

總體來說:結構體的內存對齊是拿空間來換取時間的做法。
在設計結構體的時候,我們既要滿足對齊,又要節省空間的做法是:讓占用空間小的成員盡量集中在一起。

(3)練習
//練習1
struct S1
{
char c1;
int i;
char c2;
};
printf("%d\n", sizeof(struct S1)); //輸出結果:12(最大對齊數為4)
//練習2
struct S2
{
char c1;
char c2;
int i;
};
printf("%d\n", sizeof(struct S2)); //輸出結果:8(最大對齊數為4)
//練習3
struct S3
{
double d;
char c;
int i;
};
printf("%d\n", sizeof(struct S3)); //輸出結果:16(最大對齊數為8)
//練習4-結構體嵌套問題
struct S4
{
char c1;
struct S3 s3;
double d;
};
printf("%d\n", sizeof(struct S4)); //輸出結果:32(最大對齊數為8)

(4)修改對齊數
#pragma pack(1) //設置默認對齊數為1
struct S2
{
char c1;
int i;
char c2;
};
#pragma pack() //取消設置的默認對齊數,還原為默認
注:修改的對齊數只能設置為2的n次方,操作時每個變量的對齊數都是取其自身對齊數和設置對齊數中較小的值。

5.結構體傳參——建議傳結構體指針
(1)函數傳參的時候,參數是需要壓棧,會有時間和空間上的系統開銷。
(2)如果傳遞一個結構體對象的時候,結構體過大,參數壓棧的的系統開銷比較大,所以會導致性能的下降。

6.位段
位段的聲明和結構體是類似的,有兩個不同:
(1)位段的成員必須是 int、unsigned int 或signed int;
(2)位段的成員名后邊有一個冒號和一個數字。
例如:A就是一個位段類型
struct A
{
int _a:2;
int _b:5;
int _c:10;
int _d:30;
};
注:后面的數字表示該變量會占用所開辟空間的比特位數,比特位的權值大小是未知的,字節內部其比特位的權值大小與硬件有關。
printf("%d\n", sizeof(struct A)); //位段A的大小為8字節(壓縮存儲原則)

位段的跨平臺問題:
(1)int 位段被當成有符號數還是無符號數是不確定的;
(2)位段中最大位的數目不能確定;(16位機器最大16,32位機器最大32,寫成27,在16位機器會出問題)
(3)位段中的成員在內存中從左向右分配,還是從右向左分配標準尚未定義;
(4)當一個結構包含兩個位段,第二個位段成員比較大,無法容納于第一個位段剩余的位時,是舍棄剩余的位還是利用,這是不確定的。

二、枚舉(顧名思義就是列舉,把可能的取值一一列舉)
1.枚舉類型的定義
enum Day //星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
}; //{}中的內容是枚舉類型的可能取值,也叫枚舉常量
注:這些可能取值都是有值的,默認從0開始,依次遞增1,當然在定義的時候也可以賦初值,其后依次遞增。
2.枚舉的優點
(1)增加代碼的可讀性和可維護性;
(2)和#define定義的標識符比較枚舉有類型檢查,更加嚴謹;
(3)防止了命名污染(封裝);
(4)便于調試;
(5)使用方便,一次可以定義多個常量。
3.枚舉的使用
enum Color //顏色
{
RED=1,
GREEN=2,
BLUE=4
};
enum Color clr = GREEN; //只能拿枚舉常量給枚舉變量賦值,才不會出現類型的差異

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

1.聯合的聲明和定義
//聯合類型的聲明
union Un
{
char c;
int i;
};
//聯合變量的定義
union Un un;
//計算聯合變量的大小
printf("%d\n", sizeof(un));
2.聯合的特點
聯合的成員是共用同一塊內存空間的,這樣一個聯合變量的大小,至少是最大成員的大小(因為聯合至少得有能力保存最大的那個成員)。
聯合體中所有的變量共享空間,故可理解為每個成員都是第一個成員。
應用:判斷當前計算機的大小端存儲(部分代碼)
union Un
{
int i;
char c;
};
int main()
{
union Un obj;
obj.i=0;
obj.c=1;
printf("%d\n",obj.c);
} //輸出為1則是小端,輸出為0則是大端
3.聯合大小的計算(聯合也要考慮內存對齊)
(1)聯合的大小至少是最大成員的大小。
(2)當最大成員大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍。
例如:
union Un1
{
char c[5];
int i;
};
union Un2
{
short c[7];
int i;
};
//下面輸出的結果是什么?
printf("%d\n", sizeof(union Un1)); 輸出結果:8(最大對齊數為4)
printf("%d\n", sizeof(union Un2)); 輸出結果:16(最大對齊數為4)

向AI問一下細節

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

AI

沂水县| 通山县| 任丘市| 朝阳县| 开封市| 惠州市| 静海县| 开江县| 西充县| 肥城市| 自治县| 峡江县| 巴彦淖尔市| 澎湖县| 兰溪市| 顺平县| 广宗县| 灌南县| 莱阳市| 壤塘县| 达孜县| 奇台县| 泾川县| 股票| 塔城市| 彰化县| 丁青县| 定州市| 永年县| 白银市| 崇州市| 诏安县| 扎赉特旗| 金塔县| 金寨县| 行唐县| 德昌县| 新乐市| 南宁市| 左权县| 聂拉木县|