網站首頁 編程語言 正文
1.結構體
1.1結構體類型的聲明
結構是一些值的集合,這些值稱為成員變量。結構的每個成員可以是不同類型的變量
這里給大家舉個列子演示一下:
//定義一個學生的結構體
typedef struct Stu
{
char name[20];//姓名
int age;//年齡
char sex[5];//性別
char id[15];//學號
}Stu;//分號不能丟
在這個結構體里面我們定義了學生的名字,年齡,性別,學號這些變量,這樣的變量就叫做成員變量。
結構的成員可以是標量、數組、指針,甚至是其他結構體。
這里的typedef是將結構體重命名為Stu。
1.2結構的自引用
上面我們說到了成員變量也可以為結構體,我們不妨大膽的猜想一下,結構體內可以包含一個類型為自身結構體的成員嗎?
答案當然是可以的,不過有需要我們注意的地方下面給大家用代碼的形式演示一下:
//1.錯誤引用
struct Node
{
int data;
struct Node next;
};
//2.正確引用
struct Node
{
int data;//數據
struct Node* next;//地址
};
對比上面的代碼正確的代碼比錯誤的多一個' * ',代表傳地址我們來分析一下錯誤的地方,穿了一個結構體進去,那么我們這個結構體的大小是多少呢,顯然沒辦法計算,結構題內套一個結構體,然后這個結構體又套一起進去,類似無條件遞歸,編譯器也會報錯。那么我們來看正確的代碼,
結構體分為兩部分,一部分存放數據,一部分存放地址,當我需要的時候我們根據地址找到內嵌的結構體,這樣就可以講這些結構體串起來了,當我們訪問到最后一個時,我們只需要給它一個NULL就停止了,這樣是不是就很完美了呢。
1.3結構體變量的定義和初始化
有了結構體類型怎么定義和初始化結構體變量呢,其實很簡單,給大家演示一下:
struct Point
{
int x;
int y;
}p1; //1.聲明類型的同時定義變量p1
struct Point p2; //2.定義結構體變量p2
//3.初始化:定義變量的同時賦初值
struct Point p3 = { x , y };
1.4結構體內存對齊
我們知道int的大小為4個字節,char的大小為1個字節,每個數據類型都有大小,那么結構體大小又是多少呢,該怎么計算呢?
這里需涉及到一個知識點就是內存對齊:
1. 第一個成員在與結構體變量偏移量為0的地址處。
2. 其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處。 對齊數 = 編譯器默認的一個對齊數 與 該成員大小的較小值。 VS中默認的值為8
3. 結構體總大小為最大對齊數(每個成員變量都有一個對齊數)的整數倍。
4. 如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整 體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍
文字的形式可能有點抽象,下面用圖來給大家演示一下:
為什么存在內存對齊?
大部分的參考資料都是如是說的:
1. 平臺原因(移植原因): 不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特定類型的數據,否則拋出硬件異常。
2. 性能原因: 數據結構(尤其是棧)應該盡可能地在自然邊界上對齊。 原因在于,為了訪問未對齊的內存,處理器需要作兩次內存訪問;而對齊的內存訪問僅需要一次訪問
總體來說就是拿空間換時間的做法。
那我們在設計結構體的時候想要節省空間就要做到,讓占用空間小的成員盡量集中在一起。
1.5結構體傳參
我們知道在傳參的時候有兩種方式,傳值和傳址。那么在結構體傳參的時候我們通常采用結構體地址傳參。
函數傳參的時候,參數是需要壓棧,會有時間和空間上的系統開銷。
如果傳遞一個結構體對象的時候,結構體過大,參數壓棧的的系統開銷比較大,所以會導致性能的
下降。
代碼演示如下:
struct S
{
int data[1000];
int num;
};
struct S s = { {1,2,3,4},1000 };//初始化賦值
void print1(struct S* pc)用struct S*的指針接收
{
printf("%d\n", pc->num);
}
int main()
{
print1(&s);//傳地址
return 0;
}
1.6結構體實現位段(位段的填充&可移植性)
位段的聲明和結構是類似的,有兩個不同:
1.位段的成員必須是 int、unsigned int 或signed int 。
2.位段的成員名后邊有一個冒號和一個數字
如下圖,A就是一個位段
struct A
{
int _a:2;
int _b:5;
int _c:10;
int _d:30;
};
位段的內存分配:
1. 位段的成員可以是 int unsigned int signed int 或者是 char (屬于整形家族)類型
2. 位段的空間上是按照需要以4個字節( int )或者1個字節( char )的方式來開辟的。
3. 位段涉及很多不確定因素,位段是不跨平臺的,注重可移植的程序應該避免使用位段
位段的跨平臺問題:
1. int 位段被當成有符號數還是無符號數是不確定的。
2. 位段中最大位的數目不能確定。(16位機器最大16,32位機器最大32,寫成27,在16位機 器會出問題。
3. 位段中的成員在內存中從左向右分配,還是從右向左分配標準尚未定義。
4. 當一個結構包含兩個位段,第二個位段成員比較大,無法容納于第一個位段剩余的位時,是 舍棄剩余的位還是利用,這是不確定的。
2.枚舉
枚舉就是列舉,例如一周有七天可以列舉,三原色可以列舉,性別可以列舉
2.1枚舉類型的定義
enum Color//顏色
{
RED,//0
GREEN,//1
BLUE//2
};
這里定義的 enum Color 就是是枚舉類型。
{}中的內容是枚舉類型的可能取值,也叫 枚舉常量 。
這些可能取值都是有值的,默認從0開始,一次遞增1,當然在定義的時候也可以賦初值,RED=1,GREEN=2,BLUE=100,都是可以的。
2.2枚舉的優點
1. 增加代碼的可讀性和可維護性
2. 和#define定義的標識符比較枚舉有類型檢查,更加嚴謹。
3. 防止了命名污染(封裝)
4. 便于調試
5. 使用方便,一次可以定義多個常量
3.聯合
3.1聯合類型的定義
聯合也是一種特殊的自定義類型
這種類型定義的變量也包含一系列的成員,特征是這些成員公用同一塊空間(所以聯合也叫共用體)。 比如:
//聯合類型的聲明
union Un
{
char c;
int i;
};
//聯合變量的定義
union Un un;
//計算連個變量的大小
printf("%d\n", sizeof(un));//計算出來結果為4
3.2聯合的特點
聯合的成員是共用同一塊內存空間的,這樣一個聯合變量的大小,至少是最大成員的大小(因為聯合至少得有能力保存最大的那個成員)。
上面的例子在聯合體Un中最大的成員為int占4個字節,所以聯合體Un的大小也為4個字節。
3.3聯合大小的計算
聯合的大小至少是最大成員的大小。
當最大成員大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍。
下面兩個例子中的計算方法和上面內存圖解差不多,大家可以研究一下。
union Un1
{
char c[5];
int i;
};
union Un2
{
short c[7];
int i;
};
//下面輸出的結果是什么?
printf("%d\n", sizeof(union Un1));//8
printf("%d\n", sizeof(union Un2));//16
原文鏈接:https://blog.csdn.net/m0_56653788/article/details/123890947
相關推薦
- 2022-06-16 .Net?Core解決WebAPI中返回時間格式帶T的問題_實用技巧
- 2022-06-01 Python使用list列表和tuple元組的方法_python
- 2022-07-12 CSS樣式:樣式的沖突 樣式的繼承 偽元素 偽類
- 2022-03-27 基于rsync寫腳本實現多節點多服務器文件一鍵同步的方法_相關技巧
- 2022-09-10 python中isoweekday和weekday的區別及說明_python
- 2022-08-15 Python?time模塊之時間戳與結構化時間的使用_python
- 2022-11-10 android時間選擇控件之TimePickerView使用方法詳解_Android
- 2023-01-13 Qt中QList與QLinkedList類的常用方法總結_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支