C語言重點散知識整理(二)

2021-10-21 19:59:12 字數 4366 閱讀 2821

1.逗號隔開;

2.從左向右依次執行,但是以最後乙個表示式為主;

eg:int len = (3 + 4, 5 + 6);

結果:len = 11

1.extern (宣告外部變數)

備註:這裡說的是「宣告」,宣告乙個變數或者函式是外部變數;

思考:為什麼要這麼做呢,如果引入這個變數或者函式所在檔案的標頭檔案就可以直接訪問它們,似乎 extern 沒必要。這麼想也沒錯,但是如果我們引用了標頭檔案,就意味著這個標頭檔案中所有的函式和變數我們都可以訪問修改,這是嚴重缺乏安全性的,所以 extern 就顯得格外重要了,它可以只訪問某個函式或變數,更安全。

全域性變數和函式都具有外部鏈結屬性,通過在主函式(別的檔案)中使用 「extern」 宣告後即可使用;

內部鏈結屬性:在全域性變數或函式前加 「static」,即具有內部鏈結屬性,是本原始檔的私有產物,就不可以被 extern 使用;

這裡有篇文章詳細介紹了它的使用:extern鏈結

2.聯合體 union

特性:(所有成員記憶體共享)

a.開闢的空間由裡面的變數共享,它的所有成員相對於基位址的偏移量都為0,即所有成員的起始位址都一樣;

b.開闢空間大小是由最大的位元組型別決定;

c.乙個聯合體在定義時,只能有乙個成員設定初始值;

eg://乙個聯合體最多只能有乙個字段初始值設定項

char arr[3]

;int b =10;

};大小端問題

可以利用聯合體來測試大小端,以下有兩篇文章講解比較詳細,可以了解學習下:

大小端詳解1

大小端詳解2

3.結構體 struct

定義和使用:

//1.先宣告後定義

struct 結構體名 ;

struct 結構體名 變數名;

//2.宣告+定義

struct 結構體名

變數名1

, 變數名2

;//3.直接定義

struct

變數名;

//備註:第一種寫法太複雜,可以利用 typedef 給結構體重命名

typedef

struct mystruct_new

newname;

//結構體新名字

newname value_new;

struct mystruct_old ;

struct mystruct_old value_old;

結構體可以自引用,但是只能用指標;

也可以互相引用,但是引用之前必須先執行不完整宣告,比如你要引用結構體 c,那麼你在引用前必須要宣告結構體c才行;

struct mystruct

t;

那麼你知道乙個結構體所佔的記憶體大小是多少嗎?舉個例子

eg:

struct mystruct	;

// 這裡 sizeof(mystruct) 的大小是8

很好奇這是為什麼?明明char 是乙個位元組,那麼arr[3],應該是3個位元組,那麼b 是 int 應該是 4個位元組,所以 3 + 4 = 7才對,為啥是8?這就涉及到乙個問題,記憶體對齊問題。

記憶體對齊問題

記憶體對齊的原因:

效能原因:為了提高效能所作出的犧牲記憶體的方式;

平台原因:硬體要求;

分析:對於基本型別分析:

a.在結構體中元素是按照定義順序乙個乙個放到記憶體中去的,但是並不是緊密排列的,從結構體儲存的首位址開始,每乙個元素放置到記憶體中,它都會認為記憶體是以它自己的大小來劃分的,因此元素放置的位置一定會在自己寬度的整數上開始(以結構體變數首位址為0開始計算)

b.經過上一輪分析,檢查計算出的儲存單元是否為所有元素中最寬的元素長度的整數倍,如果是,那麼結束;如果不是就需要補齊到它的整數倍;

struct mystruct	;

//所以這裡 sizeof(mystruct) = (3 + 1) + 4 + 4 = 12;

//備註:結構體中最大對齊數是4,所以12 是 4的整數倍,所以12 就是結構體大小

包含指標,結構體的分析:

指標:只要記住32位作業系統下,指標占有4個位元組,和型別無關;

結構體:它自認為自己的對齊大小其實是器內部中最大的按個對其數,而不是它自己;

規則:(1)第乙個成員在與結構體變數偏移量為0的位址;(即結構體第乙個變數沒有對齊數)

(2)其他成員要對齊到某個對齊數的整數倍的位址處;

備註:對齊數 = 編譯器預設的乙個對齊數與該成員大小的較小值

當然,平台不同對齊數也不同;

windows 預設是 8

linux 預設是 4

(3)結構體總體大小為最大對齊數的整數倍;(除了第乙個成員外每個成員都有自己的對齊數)

(4)如果巢狀了結構體的情況,巢狀的結構體對齊到自己的最大對齊數的整數倍,結構體的整體大小就是所有最大對齊數(包含巢狀結構體的對齊數)的整數倍

eg:

typedef

struct mystruct

stu1;

typedef

struct mystruct2

stu2;

int offset_tt1 =

offsetof

(stu2, tt1)

;int offset_tt2 =

offsetof

(stu2, tt2)

;int offset_tt3 =

offsetof

(stu2, tt3)

;int offset_tt4 =

offsetof

(stu2, tt4)

;int offset_tt5 =

offsetof

(stu2, tt5)

;printf

("the length of char type is %u\n"

,sizeof

(char))

;printf

("the length of int type is %u\n"

,sizeof

(int))

;printf

("the length of double type is %u\n"

,sizeof

(double))

;printf

("the length of mystruct type is %u\n\n"

,sizeof

(stu1));

printf

("the offset of 'double tt1 ' is %d\n"

, offset_tt1)

;printf

("the offset of 'char tt2 ' is %d\n"

, offset_tt2)

;printf

("the offset of 'stu1 tt3[3] ' is %d\n"

, offset_tt3)

;printf

("the offset of 'char tt4 ' is %d\n"

, offset_tt4)

;printf

("the offset of 'char tt5 ' is %d\n\n"

, offset_tt5)

;printf

("the length of the struct is %u\n\n"

,sizeof

(stu2)

);

執行結果:

分析:

typedef

struct mystruct

stu1;

typedef

struct mystruct2

stu2;

4.列舉 enum

enum 列舉名

;列舉是一堆元素的集合,他們之間用逗號隔開;

列舉元素的值都是整數。第乙個列舉成員的預設值為0,後續列舉成員的值在前乙個成員上加1。也可以自定義設定列舉成員的值,從而自定義某個範圍內的整數。

有個文章可以了解學習下:鏈結

5.巨集(#define)

列舉和巨集可以結合這篇文章一起學習,c++知識高階之#defines使用優化

題外話:

標頭檔案和原始檔:

標頭檔案:宣告函式(c語言),宣告類(c++),一般檔案字尾為 「.h」

原始檔:定義函式(c語言),定義類(c++),檔案字尾為 「.c 「 / 」.cpp」,但是在定義之前要先引用標頭檔案;

標頭檔案和原始檔屬於乙個模組。

C語言重點散知識整理(三)

左值 放在等號左邊的值,代表其表示的儲存空間 指標可以作為左值是因為它是乙個變數 右值 放在等號右邊的值,變數放在右邊代表其所代表的內容 資料比較基礎,這裡不詳細介紹,這裡只單獨拿出來強調陣列作為函式的引數時的變化 1.一維陣列作為函式傳遞的引數時,它會降級成為乙個指向一維陣列元素的指標 2.二維陣...

C語言重點整理

c語言重點整理 1.sizeof與strlen的區別與聯絡 a sizeof sizeof 是運算子,在標頭檔案中typedef為unsigned int,其值在編譯時即計算好了,引數可以是陣列 指標 型別 物件 函式等。它的功能是 獲得保證能容納實現所建立的最大物件的位元組大小。由於在編譯時計算,...

C語言重點知識歸納

三種迴圈結構 a for while do while 三種。b for迴圈當中必須是兩個分號,千萬不要忘記。c 寫程式的時候一定要注意,迴圈一定要有結束的條件,否則成了死迴圈。d do while 迴圈的最後乙個while 的分號一定不能夠丟。當心上機改錯 do while迴圈是至少執行一次迴圈。...