目錄
1.?結(jié)構(gòu)體(Struct)
1.1 C++ 結(jié)構(gòu)體和 C 語言結(jié)構(gòu)體的區(qū)別
1.2 結(jié)構(gòu)體的對(duì)齊方式
2. 聯(lián)合體(Union)
2.1 聯(lián)合體特性
3.?結(jié)構(gòu)體和聯(lián)合體的區(qū)別
1.?結(jié)構(gòu)體(Struct)
????????在 C 語言中,結(jié)構(gòu)體是一種自定義的復(fù)合數(shù)據(jù)類型,允許將不同數(shù)據(jù)類型的變量組合成一個(gè)單一的實(shí)體。結(jié)構(gòu)體可以包含多個(gè)成員,每個(gè)成員可以是不同的數(shù)據(jù)類型,如整數(shù)、浮點(diǎn)數(shù)、字符、數(shù)組等。
????????結(jié)構(gòu)體的定義通常在函數(shù)外部,并且在函數(shù)內(nèi)部可以聲明和使用結(jié)構(gòu)體類型的變量。結(jié)構(gòu)體的定義包含了結(jié)構(gòu)體的名稱和結(jié)構(gòu)體成員的列表,每個(gè)成員都有一個(gè)名稱和一個(gè)數(shù)據(jù)類型。結(jié)構(gòu)體的成員可以通過成員運(yùn)算符(.)來訪問。
以下是一個(gè)簡(jiǎn)單的 C語言 結(jié)構(gòu)體的示例:
#include <stdio.h>
// 定義一個(gè)名為Student的結(jié)構(gòu)體
struct Student {
int roll_no; // 學(xué)號(hào)
char name[50]; // 姓名
int age; // 年齡
float score; // 分?jǐn)?shù)
};
int main() {
// 聲明并初始化一個(gè)Student類型的結(jié)構(gòu)體變量
struct Student student1 = {101, "Alice", 20, 95.5};
// 訪問結(jié)構(gòu)體成員并輸出
printf("Roll No: %d\n", student1.roll_no);
printf("Name: %s\n", student1.name);
printf("Age: %d\n", student1.age);
printf("Score: %.2f\n", student1.score);
return 0;
}
1.1 C++ 結(jié)構(gòu)體和 C 語言結(jié)構(gòu)體的區(qū)別
????????C++ 中的結(jié)構(gòu)體和 C 語言中的結(jié)構(gòu)體在語法上基本上是一致的,但在 C++ 中,結(jié)構(gòu)體還具有類的特性,包括封裝、繼承和多態(tài)等,從而與 C 語言中的結(jié)構(gòu)體有一些區(qū)別。
主要區(qū)別如下:
- 成員函數(shù):C 的結(jié)構(gòu)體內(nèi)不允許有函數(shù)存在,C++ 中的結(jié)構(gòu)體可以包含成員函數(shù),且允許該函數(shù)是虛函數(shù),這是與 C 語言中的結(jié)構(gòu)體最大的不同之一。C++ 中的結(jié)構(gòu)體可以像類一樣定義成員函數(shù),可以在結(jié)構(gòu)體內(nèi)部綁定成員函數(shù)的實(shí)現(xiàn),并在結(jié)構(gòu)體對(duì)象上調(diào)用這些成員函數(shù)。
- 訪問控制:C++ 中的結(jié)構(gòu)體可以使用 public、protected、private 關(guān)鍵字來限制成員變量的訪問權(quán)限,從而實(shí)現(xiàn)封裝性;而 C 語言中的結(jié)構(gòu)體對(duì)內(nèi)部成員變量的訪問權(quán)限只能是 public,可以在任何地方被訪問。
- 繼承:C++ 中的結(jié)構(gòu)體可以通過繼承從其他結(jié)構(gòu)體或派生類,從而實(shí)現(xiàn)繼承的特性,包括單繼承和多繼承;而 C 語言中的結(jié)構(gòu)體沒有繼承的概念。
- 構(gòu)造函數(shù)和析構(gòu)函數(shù):C++ 中的結(jié)構(gòu)體可以定義構(gòu)造函數(shù)和析構(gòu)函數(shù),用于對(duì)象的初始化和清理操作;C 語言中的結(jié)構(gòu)體沒有構(gòu)造函數(shù)和析構(gòu)函數(shù)的概念。
- 默認(rèn)訪問修飾符:C++ 中的結(jié)構(gòu)體成員默認(rèn)是 private 訪問修飾符,而 C 語言中的結(jié)構(gòu)體成員默認(rèn)是 public 訪問修飾符。
- C 中使用結(jié)構(gòu)體需要加上 struct 關(guān)鍵字,或者對(duì)結(jié)構(gòu)體使用 typedef 取別名,而 C++ 中可以省略 struct 關(guān)鍵字直接使用.
1.2 結(jié)構(gòu)體的對(duì)齊方式
????????結(jié)構(gòu)體對(duì)齊根據(jù)最大類型長(zhǎng)度對(duì)齊。結(jié)構(gòu)體大小一定是最大成員的整數(shù)倍。
對(duì)齊規(guī)則:
- 結(jié)構(gòu)體變量的首地址能夠被其最寬基本類型成員的大小所整除;
????????編譯器在給結(jié)構(gòu)體開辟空間時(shí),首先找到結(jié)構(gòu)體中最寬的基本數(shù)據(jù)類型,然后尋找內(nèi)存地址能被該基本數(shù)據(jù)類型所整除的位置,作為結(jié)構(gòu)體的首地址。將這個(gè)最寬的基本數(shù)據(jù)類型的大小作為上面介紹的對(duì)齊摸數(shù)。
- 結(jié)構(gòu)體每個(gè)成員相對(duì)結(jié)構(gòu)體首地址的偏移量(offset)都是成員大小的整數(shù)倍;
????????如有需要編譯器在成員之間加上填充字節(jié)作為結(jié)構(gòu)體的一個(gè)成員開辟空間之前,編譯器首先檢查預(yù)開辟空間的首地址相對(duì)于結(jié)構(gòu)體首地址的偏移是否是本成員大小的整數(shù)倍,若是,則存放本成員,反之,則在成員和上一個(gè)成員之間填充一定的字節(jié),以達(dá)到整數(shù)倍的要求,也就是將預(yù)開辟空間的首地址后移幾個(gè)字節(jié)。
- 結(jié)構(gòu)體的總大小為結(jié)構(gòu)體最寬基本類型成員大小的整數(shù)倍;
????????如有需要編譯器會(huì)在最末一個(gè)成員之后加上填充字節(jié),結(jié)構(gòu)體總大小是包括填充字節(jié),最后一個(gè)成員滿足上面兩條以外,還必須滿足第三條,否則就必須在最后填充幾個(gè)字節(jié)以達(dá)到本條要求。
例如:
//1.
struct A
{
char c1; //大小 (char)1 + 3(填充數(shù))
int i; //大小 (int)4
char c2; //大小 (char)1 + 3(填充數(shù))
}
//該結(jié)構(gòu)體對(duì)齊數(shù)為 4(int),則結(jié)構(gòu)體大小為
//(1 + 3)+ 4 +(1+3)=12
//2.
struct A
{
char c1; //大小 (char)1 + 3(填充數(shù))
int i; //大小 (int)4
char c2; //大小 (char)1
char c3[5]; 大小 (char)1 * 5 + 2(填充數(shù)),
//因?yàn)槭且?對(duì)齊,c2為1個(gè)字節(jié),還剩3個(gè)位置給c3,
//然后c3的最后兩個(gè)字節(jié)位置再開辟下一行,新一行沒有滿足4,則再加2個(gè)填充數(shù)。
}
//該結(jié)構(gòu)體對(duì)齊數(shù)為 4(int),加上一個(gè)char類型的數(shù)組
//可以看作有5個(gè)char類型存入內(nèi)存中,則結(jié)構(gòu)體大小為:
//(1+3)+ 4 + 1 + 5 + 2 =16
//3.
struct A
{
char c1;//1+3
int i;//4
char c2;//1+7
double c[5];//40
};
//該結(jié)構(gòu)體對(duì)齊數(shù)為 8(double),加上一個(gè)double類型的數(shù)組
//可以看作有5個(gè)double類型存入內(nèi)存中,則結(jié)構(gòu)體大小為:
//(1+3)+ 4 + 1 + 7 + (8*5) =56
2. 聯(lián)合體(Union)
????????在 C 語言中,聯(lián)合體是一種特殊的數(shù)據(jù)結(jié)構(gòu),可以在內(nèi)存中共享同一段存儲(chǔ)空間來存儲(chǔ)不同類型的數(shù)據(jù)。與結(jié)構(gòu)體類似,聯(lián)合體也是一種用戶自定義的數(shù)據(jù)類型,可以包含多個(gè)不同類型的成員變量。
????????聯(lián)合體的定義使用關(guān)鍵字‘union’,后面緊跟聯(lián)合體的名稱和一對(duì)花括號(hào),括號(hào)中定義了聯(lián)合體的成員變量,每個(gè)成員變量有自己的名稱和數(shù)據(jù)類型。
#include <stdio.h>
// 定義一個(gè)聯(lián)合體
union Data {
int i;
float f;
char c;
};
int main() {
union Data data; // 聲明一個(gè)聯(lián)合體變量data
data.i = 42; // 給聯(lián)合體的整數(shù)成員賦值
printf("data.i = %d\n", data.i); // 輸出整數(shù)成員的值
data.f = 3.14; // 給聯(lián)合體的浮點(diǎn)數(shù)成員賦值
printf("data.f = %.2f\n", data.f); // 輸出浮點(diǎn)數(shù)成員的值
data.c = 'A'; // 給聯(lián)合體的字符成員賦值
printf("data.c = %c\n", data.c); // 輸出字符成員的值
// 注意:聯(lián)合體的不同成員共享同一塊內(nèi)存空間,賦值一個(gè)成員會(huì)影響其他成員的值
printf("data.i = %d, data.f = %.2f, data.c = %c\n", data.i,data.f, data.c);
//data.i = 1078523201, data.f = 3.14, data.c = A
return 0;
}
2.1 聯(lián)合體特性
- 聯(lián)合體是一個(gè)結(jié)構(gòu);
- 它的所有成員相對(duì)于基地址的偏移量都為 0 ;
- 次結(jié)構(gòu)空間要大到足夠容納最“寬”的成員;
- 其對(duì)齊方式要適合其中所有的成員;
3.?結(jié)構(gòu)體和聯(lián)合體的區(qū)別
????????(1)結(jié)構(gòu)體中的每個(gè)成員都占用獨(dú)立的內(nèi)存空間,而聯(lián)合體中的所有成員共享同一塊內(nèi)存空間。這意味著,在聯(lián)合體中只有一個(gè)成員變量能夠同時(shí)存儲(chǔ)值,而其他成員變量會(huì)被覆蓋;
????????(2)結(jié)構(gòu)體的內(nèi)存占用大小等于所有成員的內(nèi)存大小之和,而聯(lián)合體的內(nèi)存占用大小等于其最大成員的內(nèi)存大小,因此,聯(lián)合體在內(nèi)存占用上通常比結(jié)構(gòu)體更節(jié)??;
????????(3)結(jié)構(gòu)體的成員可以同時(shí)被訪問和修改,而聯(lián)合體的成員只能同時(shí)訪問和修改一個(gè)成員。這是因?yàn)槁?lián)合體的成員共享同一塊內(nèi)存空間,修改其中一個(gè)成員會(huì)影響其他成員的值。
????????(4)結(jié)構(gòu)體的成員在內(nèi)存中按照定義的順序依次排列,而聯(lián)合體的所有成員共享同一塊內(nèi)存空間,因此只有一個(gè)成員可以存儲(chǔ)有效值;
????????(5)結(jié)構(gòu)體的初始化可以為每個(gè)成員分別賦值,而聯(lián)合體的初始化只能對(duì)其中一個(gè)成員賦值。文章來源:http://www.zghlxwxcb.cn/news/detail-728335.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-728335.html
到了這里,關(guān)于【基礎(chǔ)知識(shí)】結(jié)構(gòu)體(struct)和聯(lián)合體(union)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!