梓益C語言學習筆記之結構體-共用體-枚舉
有人說,我們需要將不同類型的數據組合成一個整體,於是,就有了結構體
一、結構體的概念:
一種或多種基本類型或構造類型的數據的集合。
二、定義方法:
先定義結構體類型,再去定義結構體變量
struct 結構體類型名{
成員列表
};
如:
struct stu{
int num;
char name[20];
char sex;
};
struct stu lucy,bob,lilei;//定義了三個struct stu類型的變量
每個變量都有三個成員,分別是num name sex
通常咱們將一個結構體類型重新起個類型名,用新的類型名替代原先的類型
**最常用的定義結構體的方法是:
typedef struct stu{
int num;
char name[20];
char sex;
}STU;
STU lucy;
三、初始化及使用:
typedef struct stu{
int num;
char name[20];
char sex;
}STU;
STU lucy={101,"lucy",'f'};
STU bob;
bob.num=101;//bob是個結構體變量,但是bob.num是個int 類型的變量
bob.name 是個字符數組,是個字符數組的名字,代表字符數組的地址,是個常量
bob.name ="bob";//是不可行,是個常量
strcpy(bob.name,"bob");
四、結構體數組
結構體數組是個數組,由若干個相同類型的結構體變量構成的集合
1、結構體數組的定義方法:
struct stu{
int num;
char name[20];
char sex;
};
struct stu edu[3];//定義了一個struct stu 類型的結構體數組edu,
這個數組有3個元素分別是edu[0] 、edu[1]、edu[2]
可以這樣賦值:STU edu[3]={
{101,"Lucy",78},
{102,"Bob",59.5},
{103,"Tom",85}
};
2、數組元素的使用
edu[0].num =101;//用101給edu數組的第0個結構體變量的num賦值
strcpy(edu[1].name,"lucy");
五、結構體指針
即結構體的地址,結構體變量存放內存中,也有起始地址
定義一個變量來存放這個地址,那這個變量就是結構體指針變量。
1、結構體指針變量的定義方法:
struct stu{
int num;
char name[20];
};
struct stu * p;//定義了一個struct stu *類型的指針變量,變量名是p,p佔4個字節,用來保存結構體變量的地址編號
使用: struct stu boy;
p=&boy;
訪問結構體變量的成員方法:
boy.num=101;//可以,通過結構體變量名.成員名
(*p).num=101;//可以,*p相當於p指向的變量boy
p->num=101;//可以,指針->成員名
通過結構體指針來引用指針指向的結構體的成員,前提是指針必須先指向一個結構體變量。
六、結構體內存分配
爲什麼要有字節對齊?
用空間來換時間,提高cpu讀取數據的效率
結構體變量大小是所有成員之和
規則1:結構體分配內存時哪個基本類型的成員佔字節數多,就以它的大小爲單位開闢內存,
在gcc中出現了double類型的,例外
1:成員中只有char型數據 ,以1字節爲單位開闢內存。
2:成員中出現了short int 沒有更大字節數的基本類型數據以2字節爲單位開闢內存
3、出現了int float 沒有更大字節的基本類型數據的時候以4字節爲單位開闢內存。
4、出現了double類型的數據
情況1:
在vc裏,以8字節爲單位開闢內存。
情況2:
在gcc裏,以4字節爲單位開闢內存。
無論是那種環境,double型變量,佔8字節。
注意:
如果在結構體中出現了數組,數組可以看成多個變量的集合。
如果出現指針的話,沒有佔字節數更大的類型的,以4字節爲單位開闢內存。
在內存中存儲結構體成員的時候,按定義的結構體成員的順序存儲。
例1:struct stu{
char sex;
int age;
}lucy;
lucy的大小是4的倍數。
規則2:字節對齊
1:char 1字節對齊 ,即存放char型的變量,內存單元的編號是1的倍數即可。
2:short int 2字節對齊 ,即存放short int 型的變量,起始內存單元的編號是2的倍數即可。
3:int 4字節對齊 ,即存放int 型的變量,起始內存單元的編號是4的倍數即可
4:long int 在32位平臺下,4字節對齊 ,即存放long int 型的變量,起始內存單元的編號是4的倍數即可
5:float 4字節對齊 ,即存放float 型的變量,起始內存單元的編號是4的倍數即可
6:double
1.vc環境下
8字節對齊,即存放double型變量的起始地址,必須是8的倍數,double變量佔8字節
2.gcc環境下
4字節對齊,即存放double型變量的起始地址,必須是4的倍數,double變量佔8字節。
注意3:當結構體成員中出現數組的時候,可以看成多個變量。
注意4:開闢內存的時候,從上向下依次按成員在結構體中的位置順序開闢空間
例1:
struct stu{
char a;
short b;
int c;
}temp;
例3://temp 8個字節
#include<stdio.h>
struct stu{
char a;
short int b;
int c;
}temp;
結果分析:
a的地址和b的地址差2個字節
b的地址和c的地址差2個字節
例4:temp的大小爲12個字節
#include<stdio.h>
struct stu{
char a;
int c;
short int b;
}temp;
結果分析:
a和c的地址差4個字節
c和b的地址差4個字節
例5:
struct stu{
char buf[10];
int a;
}temp;
//temp佔 16個字節
例6:
struct stu{
char a;
double b;
}temp;
temp:
在vc中佔 16個字節 a和b的地址差8個字節
在gcc中佔 12個字節 a和b的地址差4個字節
#include<stdio.h>
struct stu{
char a;
double b;
}temp;
指定對齊原則:
使用#pragma pack改變默認對其原則
#pragma pack (value)
1.value只能是:1 2 4 8等
2.指定對齊值與數據類型對齊值相比取較小值
說明:咱們制定一個value
1:以多少個字節爲單位開闢內存
結構體成員中,佔字節數最大的類型長度和value比較,
取較小值,爲單位開闢內存
例7:
#pragma pack(2)
struct stu{
char a;
int b;
} ;
以2個字節爲單位開闢內存
#include<stdio.h>
#pragma pack(2)
struct stu{
char a;
int b;
}temp;
int main()
{
printf("%d\n",sizeof(temp));
printf("%p\n",&(temp.a));
printf("%p\n",&(temp.b));
return 0;
}
temp的大小爲6個字節
a和b的地址差2個字節
如:如果指定對齊值:
設爲1:則short、int、float等均爲1
設爲2:則char仍爲1,short爲2,int 變爲2
七、位段
在結構體中,以位爲單位的成員,咱們稱之爲位段(位域)。
struct packed_data{
unsigned int a:2;
unsigned int b:6;
unsigned int c:4;
unsigned int d:4;
unsigned int i;
} data;
對於位段成員的引用如下:
data.a =2
賦值時,不要超出位段定義的範圍;
如段成員a定義爲2位,最大值爲3,即(11)2
所以data.a =5,就會取5的低兩位進行賦值 101
八、共用體
**每次只能使用共用體的一個變量
幾種不同類型的變量存到同一段內存單元中,幾個變量所使用空間相互重疊
這種幾個不同的變量共同佔用一段內存的結構,在C語言中,被稱作“共用體”類型結構
共用體所有成員佔有同一段地址空間
共用體的大小是其佔內存長度最大的成員的大小
typedef union data{
short int i;
char ch;
float f;
}DATA;
DATA temp2;
共用體temp2佔4個字節,即i、ch、f共用4個字節
九、枚舉
將變量的值一一列舉出來,變量的值只限於列舉出來的值的範圍內
例:
定義枚舉類型 week
enum week //枚舉類型
{
mon,tue,wed,thu,fri,sat,sun
};
enum week workday,weekday;//枚舉變量
workday與weekday只能取sun….sat中的一個