C語言中的自定義類型 —— 結構體.位段.聯合體和枚舉

自定義類型

  • 1. 前言
  • 2. 結構體
    • 2.1 結構體的聲明
    • 2.2 結構體變量的定義和初始化
    • 2.3 結構體的特殊聲明
    • 2.4 結構體的自引用
    • 2.5 結構體的內存對齊
    • 2.6 修改默認對齊數
    • 2.7 結構體傳參
  • 3. 位段
  • 4. 聯合體
  • 5. 枚舉
  • 6. 結言

1. 前言

在C語言中已經為用過戶提供了內置類型,如:char,short,int,long等等,但是僅僅只有這幾種類型是遠遠不夠的,并不能滿足用戶的需求,當用戶描述的對象很復雜(屬性較多)時,如一個學生,一本書,這時單一的內置類型是不行的。在前面的數據結構中已經體會到了單一內置類型的不足。而C語言為了解決這個問題,增加了結構體這種自定義的數據類型(何為自定義類型 —— 根據需要,用戶自己來設計的一種類型),讓用戶可以自己創造適合對象的類型。

2. 結構體

2.1 結構體的聲明

使用結構體時需要用到結構體的關鍵字 —— struct。什么是結構呢?結構是一些值的集合,這些值被稱作成員變量,結構的每個成員可以是不同類型的的變量,如:標量,數組,指針,甚至是其它結構體。那么如何去聲明一個結構體?如下所示:

struct tag
{member-list;
}variable-list;

tag —— 結構體標簽的名字,根據用戶的需要去設計,與變量的變量名設計一致
member-list —— 結構體的成員列表,存在一個或多個成員
variable —— 結構體的變量列表,可以省略不寫
注意:結構體末尾存在一個分號

下面就來聲明一個書這樣的結構體類型 —— 屬性有書名,作者,價格等等:

struct book
{char name[20];   // 書名char author[20]; // 作者double price;    // 價格
};

這樣我們就聲明了一個書結構體類型。

2.2 結構體變量的定義和初始化

有了結構體的聲明之后,就可以使用這個結構體的類型了,如何使用呢?—— 結構體類型就是一個模具,聲明出了結構體類型后,就可以定義出結構體類型的變量,定義方式:struct 結構體名字 + 變量名。如下所示:

struct book book1;
struct book book2;

book1 和 book2 就是結構體變量,結構體變量可以是局部變量也可以是全局變量。全局變量不僅僅可以直接創建在局部域當中,也可以在結構體聲明的同時創建結構體變量,如下所示:

struct book
{char name[20];   // 書名char author[20]; // 作者double price;    // 價格
}book5, book6; // 全局變量//全局變量
struct book book3;
struct book book4;int main()
{//局部變量struct book book1;struct book book2;return 0;
}

變量定義完畢后,需要對結構體變量里的成員初始化,怎么初始化呢?
首先初始化是在一個大括號里,初始化的順序可以與結構體的聲明中成員的順序不一致,但是最好是一致的,不一致的需要額外的操作。
具體初始化方式如下:

初始化順序與結構體聲明中的成員的順序一致:

struct book book1 = { "老鷹抓小雞", "埃伊蟹黃面", 88.8 };
struct book book2 = { "小雞自衛戰", "埃伊蟹黃面", 99.9 };

初始化順序與結構體聲明中的成員的順序不一致:

struct book book3 = { .author = "埃伊蟹黃面", .name = "小雞吃老鷹", .price = 77.7 };
struct book book4 = { .price = 109.8, .name = "小雞變老鷹", .author = "埃伊蟹黃面" };

需要用到 . 操作符來訪問具體的成員變量。
之前有提到過,結構體的成員類型不僅可以是基礎的內置類型,也可以是結構體類型,那么當結構體中存在另一個結構體類型時,又該怎么初始化呢?如下所示:

struct other
{char character;int rint;float rfloat;
};struct book
{char name[20];   char author[20]; struct other ther;double price;
};int main()
{struct book book5 = { "ppt", "ptr", { 'G', 68, 53.2 }, 9.9 };return 0;
}

結構體類型的成員變量的初始化也需要用另外的大括號括起。既然初始化完畢,我們可以嘗試將這些初始化值打印出來,但是結構體中有這么多的成員變量怎么找到要打印的變量呢?可以通過 . 操作符來訪問具體的成員變量 ,訪問方式為:結構體的名字.要訪問的變量的名字,如下所示:

struct book book5 = { "ppt", "ptr", { 'G', 68, 53.2 }, 9.9 };//單獨訪問
printf("%s\t", book5.name);
printf("%s\t", book5.author);
printf("%.2f\t", book5.price);
printf("%c\t", book5.ther.character);
printf("%d\t", book5.ther.rint);
printf("%.2f\n", book5.ther.rfloat);//一起訪問
printf("%s\t%s\t%.2f\n", book5.name, book5.author, book5.price);
printf("%c\t%d\t%.2f", book5.ther.character, book5.ther.rint, book5.ther.rfloat);

運行結果:

在這里插入圖片描述
初始化的值并不是一成不變,在初始化后,可以對自己想要改變的變量的值進行修改,具體如下:

struct book book5 = { "ppt", "ptr", { 'G', 68, 53.2 }, 9.9 };
book5.price = 99.9;
book5.ther.character = 'H';
strcpy(book5.name, "小雞的獨立");

修改后,代碼的運行結果:
在這里插入圖片描述
由上圖可知,結構體中變量的值被修改了。

2.3 結構體的特殊聲明

在聲明結構體的時候,可以不完全的聲明,之前的結構體的聲明是完全的結構體聲明。不完全的結構體的聲明是怎樣的呢?如下代碼所示:

struct
{int id;char name[20];int age;double high;
};

上面的代碼就是不完全的結構體的聲明,省略了結構體的名字,所以這種結構體也稱為匿名結構體。將結構體寫成匿名結構體后,結構體變量的創建的就只能在聲明的同時創建,因為這個結構體沒有標簽(名字)呀,怎么在局部域中創建?具體創建方式如下所示:

struct
{int id;char name[20];int age;double high;
}stu1, stu2;

對于匿名結構體類型,如果沒有對結構體類型重命名的話,基本上只能使用一次

2.4 結構體的自引用

結構體的自引用是什么意思呢?—— 結構體中包含一個或多個類型為該結構體本身類型的成員變量。數據結構中經常用到,如單鏈表的結點的結構體:

struct SListNode
{int data;struct SListNode* next;
};

上面的就是結構體的自引用。在結構體的自引用當中可以使用typedef關鍵字對結構體進行重命名,如下所示:

typedef struct SListNode
{int data;struct SListNode* next;
}SLNode;

之后SLNode就相當于是struct SListNode,既然如此,能不能將結構體內部的struct SListNode* 替換成 SLNode* 呢?不能!因為SLNode是對前面的結構體類型重命名產生的,它是后于結構體類型創建的。

2.5 結構體的內存對齊

結構體既然是個自定義類型,那么該類型的內存大小又是多少呢?不同的結構體類型中的成員變量的類型不同,成員變量的個數不同會對結構體是內存大小產生影響,而要想知道怎么不通過sizeof來計算結構體類型的大小,就得要了解結構體內存對齊
在介紹結構體內存對齊前,來計算以下兩個結構體的大小:
在這里插入圖片描述
在不了解結構體內存對齊之前,計算的方法可能是這樣:對于Test1結構體,第一個成員類型為char,所以該成員變量的內存大小為1個字節,以此類推,所以Test1結構體的內存大小一共為6個字節;對于Test2結構體,第一個成員類型為char,所以該成員變量的內存大小為1個字節,以此類推,所以Test2結構體的內存大小一共為6個字節。那么這樣的計算邏輯有沒有問題呢?接下來用sizoef來計算兩個結構體類型的大小:

在這里插入圖片描述
為什么得到的結果不是兩個6,而是Test1的內存的大小為8個字節,Test2的內存大小為12個字節呢?因為結構體的成員在存儲的時候會存在內存對齊現象。該現象涉及到了結構體當中的偏移量,何為偏移量,距離起始位置相差多少個字節就為多少偏移量,具體如下所示:
在這里插入圖片描述
明白了偏移量是什么后。接下來開始介紹結構體內存對齊的規則:

1. 結構體的第一個成員變量對齊到和結構體變量的起始位置偏移量為0的位地址
2. 其它的結構體成員變量要對齊到某個數字(對齊數)的整數倍地址處
對齊數 = 編譯器默認的一個對齊數 與 該成員變量大小的較小值
在編譯器中,vs編譯器中默認對齊數為 8
Linux中 gcc 沒有默認對齊數,對齊數就是成員自身類型的大小
3. 結構體總大小為最大對齊數(結構體中每個成員變量的對齊數中的最大值)的整數倍
4. 如果嵌套了結構體的情況,嵌套的結構體成員對齊到自己的成員中最大對齊數的整數倍處,結構體的整體大小就是最大對齊數(含嵌套結構體中的成員的對齊數)的整數倍

知道了結構體內存對齊的規則之后,接下來根據該規則計算先前的兩個結構體類型的大小:

Test1結構體的內存大小計算:
在這里插入圖片描述
Test2結構體的內存大小計算:

在這里插入圖片描述
當要計算的結構體中又嵌套了一個結構體呢?這該如何計算?接下來就來詳細的計算嵌套結構體類型的內存大小:

在這里插入圖片描述

接下來用sizeof來計算Test2結構體的內存大小:

在這里插入圖片描述
了解了內存對齊的運用之后,接下來思考為什么會存在內存對齊呢?有以下幾個原因:

1. 平臺原因
不是所有的硬件平臺都能訪問任意地址上的任意數據;某些硬件平臺只能在某些地址處取得某些特定類型的數據,否則會拋出硬件異常。
2. 性能原因
數據結構應該盡可能地在自然邊界上對齊。原因在于,為了訪問未對齊的內存,處理器需要做兩次內存訪問;而對齊的內存訪問僅需要一次訪問

總的來說:結構體的內存對齊是拿空間換取時間的做法

在前面又計算過兩個成員類型相同,成員個數相同的結構體,但是計算的結果卻不一樣,如下圖所示:
在這里插入圖片描述
這表明了在設計結構體的時候,讓占用空間小的成員盡量集中在一起,這樣就可以最大限度的節省空間

2.6 修改默認對齊數

其實vs編譯器的默認對齊數8是可以修改的,#pragma這個預處理指令就可以修改編譯器的默認對齊數。具體修改方法如下:

#pragma pack(2) // 設置默認對齊數為2
struct Test3
{char charc1;int rint;char charc2;
};
#pragma pack() // 取消設置的默認對齊數

下面與未修改默認對齊數的結構體的內存大小進行比較:
在這里插入圖片描述
當結構體在對齊方式不合適的時候,可以自己更改默認對齊數。

2.7 結構體傳參

結構體既然作為自定義類型,自然可以用作函數的參數。它與內置類型傳參的一致,又傳值傳參和傳址傳參。下面來分別寫成結構體的傳值傳參和傳址傳參。

傳值傳參:

在這里插入圖片描述
若想要訪問結構體對象中的成員,可以通過 . 操作符 來訪問。

傳址傳參:

在這里插入圖片描述

若想要訪問結構體對象中的成員,可以通過 ->操作符 來訪問。

無論是傳值傳參還是傳址傳參,都滿足我們的要求,那么到底哪種傳參方式更好一些呢?選擇傳址傳參會更好一些,為什么呢?函數傳參的時候,參數是需要壓棧的,這樣就會有時間和空間上的系統開銷;如果傳遞一個結構體對象的時候,結構體過大,參數壓棧的系統開銷比較大,會導致性能的下降。所以結構體傳參時,要傳結構體的地址

3. 位段

位段的聲明與結構體是類似的,但是存在著兩個不同:

1. 位段的成員類型可以是 int , unsigned int 或 signed int ,char ,在C99中位段成員的類型也可以選擇其它的類型
2. 位段的成員后面又一個冒號和數字

具體的聲明如下代碼所示:

struct Digital
{int m_a : 2;int m_b : 5;int m_c : 10;int m_d : 30;
};

Digital 就是一個位段。位段中的成員的冒號后面的數字是該成員變量的大小,單位是 bit ,該數字的大小不能超過成員的類型的大小,如成員的類型為 int 類型,那么該成員冒號后面的數字不能超過32。那么這個位段的大小是多少呢?又該怎么計算呢?哎!想要知道這些,就得要了解位段的內存分配:

1. 位段的成員可以是 int , unsigned int 或 signed int 或 char 等類型
2. 位段的空間是按照需要以 4個字節(int) 或者 1個字節(char) 的方式來開辟
3. 位段涉及很多不確定的因素,位段是不跨平臺的,注重可移植的程序應當避免使用位段

根據位段的內存分配方式,來計算下面位段的大小:

struct Number
{char a : 3;char b : 4;char c : 5;char d : 4;
};int main()
{//將num對象中的所有比特位都賦值為0struct Number num = { 0 };num.a = 10;num.b = 12;num.c = 3;num.d = 4;return 0;
}

大概的來推算一下,該位段的大小。前面有提到過,位段的空間是是按照4或1個字節的方式開辟的,這個位段的成員類型大多是char類型,所以開辟空間的方式每次開辟1個字節,不夠了再開辟1個字節。
首先為變量a開辟一個字節大小的空間,變量只有3bit大小,剩下5bit未被使用;接著存儲變量b,變量的大小有4bit大小,而之前為變量a開辟的剩下的空間為5bit,所以不需要再次開辟空間,剩下的5bit空間足夠存儲變量b,這樣就剩下一個bit大小的空間;
接著存儲變量c,變量c有5bit大小,剩下的空間只有1bit大小,所以需要再次開辟1個字節大小的空間,第一次開辟的空間的剩余部分被舍棄,那么變量c就直接占用新開辟的空間的5bit大小空間,剩下3bit未被使用;
接下來再來存儲變量d,變量d有4bit大小,但是剩下的空間只有3bit大小,所以需要再次開辟1個字節大小的空間,那么剩下的3bit大小的空間按照之前的假設,直接舍棄。
所以按照上面的推算位段Number的大小為3個字節。

但是還有另外一種推算方法就是剩下的空間不被舍棄,那么按照此推算方法,位段Number的大小為2個字節。

在當前環境下,結果到底是2個字節還是3個字節,用 sizeof 一求便知,結果如下:

在這里插入圖片描述
根據結果易知,在vs編譯器下推算1的方法正確。

前面有提到位段是不支持跨平臺的,由于它有許多的不確定的因素,那么這些不確定的因素有:

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

既然位段有這么多的缺陷,那么它還有什么運用場景呢?位段可以運用于網絡協議中,這里使用位段不僅能夠實現想要的效果,還能節省空間,這樣網絡傳輸的數據包大小也會較小一些,對于網絡的通暢有幫助。

在使用位段時,還需要注意:位段的幾個成員共有同一個字節,這樣有些成員的起始位置并不是某個字節的起始位置,那么這些位置處是沒有地址的。內存中每個字節分配一個地址,而一個字節的內部的bit位是沒有地址的。所以不能對位段的成員使用&操作符,如此一來就不能通過
scanf 直接給位段的成員輸入值,只能是先輸入一個值,并將該值放在一個變量中,然后賦值給位段的成員。

具體如下所示:

struct Digital dig = { 0 };
//錯誤方法 —— scanf("%d", &dig.m_a);//正確方法
int a = 0;
scanf("%d", &a);
dig.m_a = a;

4. 聯合體

如同結構體一致,聯合體也是由一個或者多個成員構成,這些成員可以是不同的類型,但是編譯器只為最大的成員分配足夠的內存空間。聯合體也有它的關鍵字 —— union。聯合體的特點是所有的成員都共用同一塊內存空間,所以聯合體也稱為:共用體。給聯合體當中的某個成員賦值,其它的成員也會跟著變化。下面來使用聯合體:
在這里插入圖片描述
如何計算聯合體的大小?

1. 聯合體的大小至少是最大成員的大小
2. 當最大成員大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍

接下來用具體的例子來明白如何計算聯合體的大小:

在這里插入圖片描述
聯合體中也存在內存對齊,該聯合體的最大對齊數為4,而該聯合體中最大成員的大小為5,不是最大對齊數的整數倍,浪費3個字節大小的空間,所以 Un1 聯合體的大小為8個字節。

下面使用聯合體來判斷當前機器是大端還是小端:首先來介紹何為大端和小端,如下圖所示:

在這里插入圖片描述
下面開始編寫代碼:

union Un
{char c;int i;
};int main()
{union Un un;un.i = 1;if (un.c == 1){printf("小端\n");}else{printf("大端\n");}return 0;
}

利用了聯合體的一個特點:所有的成員都共用同一塊內存空間,給聯合體當中的某個成員賦值,其它的成員也會跟著變化。具體的分析如下:

在這里插入圖片描述

5. 枚舉

枚舉枚舉,顧名思義就是一一列舉,把可能的值一一列,在日常生活中,天數可以被一一列舉,月份可以被一一列舉等等,而這些數據就可以使用枚舉。枚舉就是用來表示那些取值可以被一一列舉的類型。枚舉的關鍵字是 —— enum。枚舉類型的使用:

//枚舉類型的聲明
enum Day
{//枚舉類型的可能取值//這些可能取值都是常量,并且它們都是有值的//默認從 0 開始,依次遞增 1Mon,Tues,Wed,Thur,Fri,Sat,Sun
};int main()
{//枚舉類型的定義enum Day day = Sun;//打印枚舉類型Day的所有可能取值printf("%d\t", Mon);printf("%d\t", Tues);printf("%d\t", Wed);printf("%d\t", Thur);printf("%d\t", Fri);printf("%d\t", Sat);printf("%d\t", Sun);return 0}

打印結果:

在這里插入圖片描述
枚舉類型中的常量是可以在聲明的同時賦初始值的,也就是給常量初始化,如下所示:

在這里插入圖片描述

有人可能會有疑問,既然是定義常量,為什么要使用枚舉這個類型呢?#define也可以定義常量呀?也就是說,枚舉有什么優點?枚舉常量的優點有很多:

1. 增加代碼的可讀性與可維護性
2. 和#define定義的標識符比較枚舉有類型檢查,更加嚴謹
3. 便于調試,預處理階段會刪除#define定義的符號
4. 使用方便,一次可以定義多個常量
5. 枚舉常量是遵循作用域規則的,枚舉聲明在函數內,就只能在函數內使用

6. 結言

以上就是C語言中主要的自定義類型。其中最主要的是結構體類型,在學習C++時,遇到的類與結構體有著相似之處。學好它,有助于理解C++中的類類型。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79389.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79389.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79389.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

StarRocks 查詢優化器深度解析

StarRocks 查詢優化器概覽 1. Development History of StarRocks 過去五年,StarRocks 發布了三個大版本: StarRocks 1.0:通過向量化引擎和 CBO,打造極速 OLAP 數據庫。 StarRocks 2.0:通過主鍵模型、數據湖分析和查詢…

如何提高情商?(優化版)

引言 提高情商(EQ)是一個需要長期練習和自我反思的過程,核心在于理解自己、管理情緒、共情他人并有效溝通。以下是一些具體且可操作的方法,結合理論和實際場景,幫助你逐步提升: 一、核心方法:…

Python爬蟲實戰:獲取好大夫在線各專業全國醫院排行榜數據并分析,為患者就醫做參考

一、引言 在當今醫療資源豐富但分布不均的背景下,患者在選擇合適的心血管內科醫院時面臨諸多困難。好大夫在線提供的醫院排行榜數據包含了醫院排名、線上服務得分、患者評價得分等重要信息,對患者選擇醫院具有重要的參考價值。本研究通過爬取該排行榜數據,并進行深入分析,…

【AI面試準備】電商購物車AI測試設計與實施

面試題:案例實踐: 為電商購物車設計AI測試:通過用戶行為日志訓練點擊路徑預測模型,動態生成邊界條件測試用例。 為了順利通過面試,回答應結構清晰、技術深入,并突出實際應用與創新。以下為分步解答&#…

Java 中使用 Callable 創建線程的方法

一、Callable 接口概述? Callable接口位于java.util.concurrent包中,與Runnable接口類似,同樣用于定義線程執行的任務,但它具有以下獨特特性:? 支持返回值:Callable接口聲明了一個call()方法,該方法會在…

2025-SMS短信驗證服務或存風險,小心賬號隱私“失守”

近期,火絨安全情報中心監測到一款偽裝成具備SMS短信驗證碼接收服務的程序。該程序通過部署持久化后門(即僵尸網絡節點)竊取敏感信息。火絨安全提醒廣大用戶務必從官方或可信渠道下載軟件,避免因使用來路不明的程序而導致賬號被盜或…

docker部署Open WebUI下載速度慢解決方法

docker pull ghcr.nju.edu.cn/open-webui/open-webui:main改成這個就可以了

氣泡圖、桑基圖的繪制

1、氣泡圖 使用氣泡圖分析某一年中國同歐洲各國之間的貿易情況。 氣泡圖分析的三個維度: ? 進口額:橫軸 ? 出口額:縱軸 ? 進出口總額:氣泡大小 數據來源:鏈接: 國家統計局數據 數據概覽(進出口總額&…

前端面經-VUE3篇(三)--vue Router(二)導航守衛、路由元信息、路由懶加載、動態路由

一、導航守衛 vue Router 中的 導航守衛(Navigation Guards) 是一個非常重要的功能,用于在路由切換過程中,攔截、控制、檢查或延遲頁面跳轉。 你可以理解為: 🔐 “進門前的保安”,控制哪些頁面…

MATLAB實現二氧化硅和硅光纖的單模光波特性與仿真

一.二氧化硅和硅光纖的單模光波特性 利用麥克斯方程的精確解研究二氧化硅和硅亞波長直徑導線的單模光波特性。研究了單模條件、模場。 二氧化硅光纖導線是圓形截面,包層是空氣包層,階梯型變化的折射率,導線線徑D非常小長度足夠長&#xff0…

【Linux系統】第二節—基礎指令(2)

hello ~ 好久不見 自己想要的快樂要自己好好爭取! 云邊有個稻草人-個人主頁 Linux—本篇文章所屬專欄—歡迎訂閱—持續更新中 目錄 本節課核心指令知識點總結 本節基本指令詳解 07.man 指令 08.cp 指令 09.mv 指令 10.cat 指令 11.more 指令 12.less 指令 …

為了結合后端而學習前端的學習日志——【黑洞光標特效】

前端設計專欄 今天給大家帶來一個超酷的前端特效——黑洞光標!讓你的鼠標變成一個會吞噬光粒子的迷你黑洞,點擊時還會噴射出綠色能量粒子!🌠 🚀 效果預覽 想象一下:你的鼠標變成一個旋轉的黑洞&#xff0…

[硬件電路-11]:模擬電路常見元器件 - 什么是阻抗、什么是輸入阻抗、什么是輸出阻抗?阻抗、輸入阻抗與輸出阻抗的全面解析

1. 阻抗(Impedance) 定義:阻抗是電路或元件對交流信號(AC)流動的阻礙能力,用符號Z表示,單位為歐姆(Ω)。它綜合了電阻(R)、電感(L&am…

機器學習和深度學習的對比

深度 數據經過深層網絡后,語義信息表征能力強,對幾何細節信息表征能力弱。 數據依賴性 深度學習算法需要大量的數據來訓練,而傳統的機器學習使用制定的規則。所以,當數據量少時,深度學習的性能差于機器學習&#xf…

Kubernetes 安裝 minikube

安裝 minikube 在 Ubuntu 上安裝 minikube minikube 是一個工具,它可以在本地快速運行一個單節點的 Kubernetes 集群。它主要用于:本地學習 Kubernetes、測試和開發 Kubernetes 應用程序、快速嘗試 Kubernetes 的功能。 系統配置最低要求如下 CPU&#…

【學習筆記】深度學習:典型應用

作者選擇了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰寫的《Deep Learning》(人工智能領域的經典教程,深度學習領域研究生必讀教材),開始深度學習領域學習,深入全面的理解深度學習的理論知識。 之前的文章參考下面的鏈接&#xf…

ComputeShader繪制全屏純色紋理

參考 Getting Started With Compute Shaders In Unity 環境 Win10 Unity20194.40 全屏純色紋理示例 使用ComputerShader逐個像素設置顏色 ComputeShader腳本 設置紋理顏色 #pragma kernel CSMainRWTexture2D<float4> Result;//紋理 half4 solidColor;//顏色[numth…

數學實驗(Matlab語言環境和線性代數實驗)

一、Matlab語言環境和線性代數實驗 1.Matlab語言環境 Matlab簡介 Matlab&#xff1a;Matrix Laboratry 矩陣實驗室 Matlab 提供了強大的科學計算、靈活的程序設計流程、高質量的圖形可視化與界面設計等功能&#xff0c;被廣泛應用于科學計算、控制系統、信息處理等領域的分…

Android面試總結之GC算法篇

一、GC 機制核心原理與算法 面試題 1&#xff1a;Android 中為什么采用分代回收&#xff1f;分代策略如何優化 GC 效率&#xff1f; 標準答案&#xff1a; 分代回收基于對象生命周期的差異&#xff0c;將堆分為年輕代&#xff08;Young Gen&#xff09;和老年代&#xff08;Ol…

仿騰訊會議——注冊登錄UI

1、加載素材 2、新添加資源類 3、加載圖片 4、添加左側圖片 在左側添加一個標簽 選擇圖片 選擇圖片 勾選保證圖片不變形 5、修改組件名稱 6、設置密碼輸入框 5、切換 6、編輯提示框 7、定義提交和清空的槽函數 8、設置頁面標題和最先顯示頁面 9、清空登錄信息函數實現 10、清空…