溫馨提示×

溫馨提示×

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

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

自定義類型:結構體+枚舉+聯(lián)合

發(fā)布時間:2020-07-22 18:59:16 來源:網(wǎng)絡 閱讀:512 作者:wx5c863047de0a5 欄目:編程語言

自定義類型:結構體,枚舉,聯(lián)合
一、結構體
1.結構體的聲明
struct Stu
{
char name[20]; //名字
int age; //年齡
char sex[5]; //性別
char id[20]; //學號
}; //分號不能丟
注:
(1)C語言中結構體成員不能為空,C++中可以;
(2)沒有名字的結構體稱為“匿名結構體”,不建議出現(xiàn)這樣的結構體;
(3)有幾個結構體聲明就有幾種結構體類型,即使成員一模一樣,兩個結構體仍然不同。
2.結構體的自引用
直接在結構體中嵌套自身結構體作為成員在某些操作時無異于“死循環(huán)”,例如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};//初始化
注:結構體和數(shù)組一樣,可以整體初始化,但不能整體賦值!

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

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

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

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

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

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

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

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

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

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

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

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

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

向AI問一下細節(jié)

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

AI