目錄
一、結構體(struct關鍵字)
(一)聲明一個結構體數據類型
(二)結構體的成員初始化與賦值
a、結構體變量賦值
b、結構體成員初始化
c、結構體的定義形式
(三)考點:結構體在內存中所占字節數
(四)對結構體成員進行輸出
(五)例題
二、共用體(union關鍵字)
三、枚舉(enum關鍵字)
四、typedef關鍵字
五、位運算
(一)&? 按位與??
(二)|? 按位或
(三)^ 按位異或?
(四)~ 取反
(五)<< ?左移?
(六)>> ?右移
一、結構體(struct關鍵字)
????????結構體類型—用來描述復雜數據的一種類型,它是構造類型的(用戶自定義類型)一種。
(一)聲明一個結構體數據類型
1、語法:
struct 結構體名//創建抽象的數據類型
{
? ?成員列表;
};
2、理解:
(1)struct關鍵字表示在構造一個結構體類型;
(2)結構體名是用來描述結構體這個類型的一個名稱;
(3)成員列表,它定義的形式,與之前的定義變量的方式是相同的,也用之前的那些
????????數據類型定義,它不僅可以定義變量,還可以定義數組和指針變量;
????????多個成員定義變量的時候,注意要用分號隔開;
????????成員列表表示要描述的復雜數據中用到的具體的成員變量;
(4)特別注意在最后的花括號后面要加一個“;”。
3、示例:
4、結構體類型的使用:首先先定義出一個類型,再去定義需要的變量,
定義變量的形式是:struct 結構體名 變量名 即?結構體類型+變量名
eg:struct Student s;
(二)結構體的成員初始化與賦值
a、結構體變量賦值
1、示例:
注:(1)"? .? "為結構體成員運算符,優先級為1級,結合方向自左至右;
? ? ? ?(2)不能寫成s.name = "zhangsan";編譯報錯,數組不能被整體引用。
3、結構體變量與變量之間可賦值,示例:
b、結構體成員初始化
1、形式: struct student s={};
? ? ?初始化的時候,看每個成員變量具體是什么數據類型,然后根據各個成員變量自身的數據類型進行初始化;
示例:struct student s={1,"zhangsan",99};//此方法做不到只初始化一個成員
2、初始化次序不能顛倒應與結構體聲明順序保持一致;
3、結構體成員的部分初始化
示例:struct student s={ .id = 1};//其他未初始化的部分全為0;
? ? ? ? ? ?struct student s={ .name = "zhangsan" , .score = 99};//用逗號隔開
c、結構體的定義形式
形式1:先定義類型,然后定義變量
struct Student
{
};
struct Student s;
形式2:定義類型的同時定義變量
struct Student
{
}s;
示例:聲明結構體的同時定義了兩個全局變量(s1,s2)
(三)考點:結構體在內存中所占字節數
內存對齊原則:
1、默認按照計算機位數對齊,64/8=8最終大小必須是8的整數倍;(32位系統下默認4字節對齊)
2、從結構體中的成員中查找最大字節的成員,最終按此成員大小對齊;
3、把每個成員按照聲明順序依次存放入內存,偏移量/sizeof(成員)必須能夠整除。
(注:32位的平臺 :如果有超過4字節 ,按照4字節對齊;如果沒有超過4字節的,則
按成員變量中最大對齊 ;64位的平臺:如果超過4字節的,按超過的最大的成員變量對
齊,如果沒有超過4字節的,則按成員變量中最大對齊)
示例:
圖中代碼printf("%lu\n",sizeof(struct Demo));運行結果為12(占12個字節)
注:內存對齊的原因:空間換時間,提高程序運行效率
(四)對結構體成員進行輸出
1、->:指向結構體成員運算符;
2、指針用指向結構體成員運算符(->),變量用結構體成員運算符(.);
3、輸出函數1:
注:該函數為值傳遞(過程需要拷貝);不建議使用
4、輸出函數2:
注:該函數為指針傳參(效率更好)
(五)例題
1、結構體的遍歷
2、采用回調函數按學生成績排序
3、采用qsort函數按學生名字排序
二、共用體(union關鍵字)
1、共用體:(union)它是共用一塊內存空間(共用了最大成員的空間);
2、語法:
union 共用體名
{
? ?成員變量;
};
3、示例:
4、共用相同的內存空間(所以稱為共用體)
運行結果:4(共占4個字節)
5、訪問時只有最后被賦值的變量是有效的(彼此內存相互覆蓋)
運行結果為1
6、4個字節被3個長度不同的變量共享時,共享總是從起始部分開始共享的(所有成員起始地址是相同的);
7、用共用體判斷計算機大小端存儲:
三、枚舉(enum關鍵字)
1、含義:將變量的值一個一個列舉出來;變量的值只限于列舉出來的值的范圍內;
2、作用:為了提高代碼的可讀性;
3、語法
enum 枚舉名
{
? ?列舉各種值,//不是成員,是可能的取值(全為常量)
};
注:列舉各種值時,用逗號隔開,不需要類型名;
4、注意事項:
(1)枚舉中逐個列舉的值,默認是從0開始;如果有給定的值,則后續沒有給值的枚舉成員依次加1;
(2)枚舉本質是一個int 類型的數據(可以放在switch中使用);
(3)每個值可以用%d輸出。
5、示例:
運行結果:sleep
運行結果為4
運行結果為2(列舉的值默認從0開始)
運行結果為13(有給定的值,后續沒有給值的枚舉常量依次+1)
四、typedef關鍵字
1、typedef——type define
? ? ?它的本意不是定義類型,是給已有的數據類型起別名。
eg:
int a ;//定義了一個int 型變量,a為變量名(具體)
typedef int a; //此時a是int類型的類型名(抽象)
2、示例:
運行結果為4
3、作用:避免寫長長的關鍵字;
此時Student為類型的類型名(抽象)
4、不建議使用其簡化,代碼可讀性差;
示例:
a為數組整型,運行結果為40
a為函數的指針的數組,sizeof(a)為80
五、位運算
(一)&? 按位與??
1、& :雙目運算符,優先級為8級,結合方向自左至右;
2、運算規則:一假則假 (任何一個為0,其結果必然為0;兩個都為1,其結果為1);
3、作用:指定位清零;
4、示例:
1001 1110?
0011 0010 &
-------------------0001 0010?
(二)|? 按位或
1、|:雙目運算符,優先級為10級,結合方向自左至右;
2、運算規則:一真則真 (任何一個為1,其結果必然為1;兩個都為0,其結果為0);
3、作用:指定位置1;
4、示例:
1001 1110?
0011 0010 |
-------------------1011 1110?
(三)^ 按位異或?
1、^:雙目運算符,優先級為9級,結合方向自左至右;
2、運算規則:相同為0,不同為1;
3、作用:指定位翻轉,其他位不變;
4、示例:
1001 1110?
0011 0010 ^
-------------------1010?1100
(四)~ 取反
1、~:單目運算符,優先級為2級,結合方向自右至左;
2、運算規則:按位取反(將0變1,1變0);
3、示例:
1001 1110 ?~
-------------------0110 0001
(五)<< ?左移?
1、<<:雙目運算符,優先級為5級,結合方向自左至右;
2、寫法:a<<n ?(表示將a這個數據左移n位 )(C語言中為邏輯左移)
3、最高位無論是1還是0全丟掉,后面補0;
4、作用:指定位清零( ~(1 << n));
5、示例:
0000 0001?
0000 0010
左移1位 ?相當于乘 2 ?
(六)>> ?右移
1、>>:雙目運算符,優先級為5級,結合方向自左至右;
2、寫法:a>>n(表示將 a這個數據 右移 n位)
3、算術右移是看符號位和看數據類型的:
(1)有符號數據類型,右移時,最高位補的是符號位; (算術右移)? ? ?
(2)無符號類型的數據,右移時,最高位補的0 ;(邏輯右移)
注:在使用右移運算符時最好定義無符號數據類型(eg:unsigned char)
4、示例:
1000
1100
-----------
0100
0010
右移1位 ?相當于除 2 ??