一、結構體
1、聲明:
方法一:
struct 類型名
{
成員變量;
}(變量名);
struct 類型名 變量名 ;//定義結構體變量
struct 類型名 變量名 = {數據,...};//定義結構體變量同時初始化
方法二:
typedef struct 類型名
{
成員變量;
} (自定義類型名);
自定義類型名 變量名 ;//定義結構體變量
注:結構體中的成員變量不可在結構體中進行初始化。
結構變量用'.'進行引用成員。
結構體指針變量用->引用成員列:
二、內存對齊
linux默認對齊數爲 4 , vs默認對齊數爲 8
#pragma pack (n);//修改默認對齊數爲n (0<n<8(4),n=0 或 n>默認值,n取默認值)
內存對齊計算方法:
1、類型所佔字節 與 默認對齊數比較 取小的作爲對齊數
2、此變量所佔總字節 + 之前所佔字節 總字節轉變爲對齊數的倍數(最接近)
3、最終總大小轉變爲 所取最大對齊數的倍數(最接近)
列:
typedef struct Test2{ //默認對齊數 8
char c; //char 1 < 8 對齊數1 佔1字節 偏移 0
int num; //int 4 < 8 以4對齊 佔4+1=5字節 5--4的倍數-->8 偏移 3
struct Test2 *Next;//鏈表 指針 4 < 8 以4對齊 佔4+8=12字節 12--4的倍數-->12 偏移 0
}p,*node; //12--所取最大對齊數倍數-->12 偏移 0 結構體大小 12
//注:此處p,和*node 爲類型名,p 結構體類型,node 結構體指針類型
代碼示例:
void structb(void){
typedef struct Test2;//結構體聲明
typedef struct Test2{ //默認對齊數 8
char c; //char 1 < 8 對齊數1 佔1字節 偏移 0
int num; //int 4 < 8 以4對齊 佔4+1=5字節 5--4的倍數-->8 偏移 3
struct Test2 *Next;//鏈表 指針 4 < 8 以4對齊 佔4+8=12字節 12--4的倍數-->12 偏移 0
}p,*node; //12--所取最大對齊數倍數-->12 偏移 0 結構體大小 12
//注:此處p,和*node 爲類型名,p 結構體類型,node 結構體指針類型
p p1;//定義結構體變量p1
p * pnew;//定義結構體指針變量 pnew
node head;//定義結構體指針變量 head
p1.c='1';
pnew=(p*)malloc(sizeof(p));//開闢一個結構體空間的大小
pnew->num=12;
//加{}好後所有設置僅在括號內有效
{
#pragma pack (4)//設置默認對齊數爲4
//聲明瞭一個結構體,結構體類型名 Test
//將結構體Test2作爲成員變量,結構體必須在其之前定義
struct Test{ //默認對齊數 4
int a; //int 4 = 4 第一個不對齊 對齊數爲4 佔4字節 偏移 0
char ch; //char 1 < 4 以1對齊 佔4+1=5個字節 5--1的倍數-->5 偏移 0
char arr[5]; //char 1 < 4 以1對齊 佔5*1+5=10個字節 10--1的倍數-->10 偏移 0
double num; //double 8 > 4 以4對齊 佔8+10=18個字節 18--4的倍數-->20 偏移 2
//tp爲Test2的結構體類型,取其中取得的最大對齊數與默認之比較
struct Test2 tp; //tp 4 = 4 以4對齊 佔12+20=32個字節 32--4的倍數-->32 偏移 0
int * p ; //int 4 = 4 以4對齊 佔4+32=36個字節 36--4的倍數-->36 偏移 0
}ta,test[10]; //36--所取最大對齊數倍數-->36 偏移 0 結構體大小 36
//注:此處ta,與test爲變量名
struct Test tb;//定義結構體變量tb
printf("Test:%d\n",sizeof(ta));
}
printf("%c\n",p1.c);
printf("%d\n",pnew->num);
printf("%p\n",&p1.c);
printf("%p\n",&p1.num);
printf("%p\n",&p1.Next);
printf("Test2:%d\n",sizeof(p1));
}
2、連續相同類型所佔字節數和 < 該類型所佔字節大小 則共同分配該類型空間
3、若類型不同,或連續相同類型所佔字節數和 > 該類型所佔字節大小,則分別開闢一塊內存空間
4、內存對齊問題與結構體類似
5、位段共用一個地址時不會發生數據覆蓋問題
void struct_bit(void)
{
struct Bit{ //聲明一個位段
int b1 : 2;//b1佔2個bit位int類型 int 4 < 8 對齊數 4 所佔字節4
char b2 : 3;//b2佔3個bit位char類型 連續同類型 b2+b3<8 共佔1個字節
char b3 : 4;//b2佔4個bit位char類型 char 1 < 8 對齊數 1 所佔字節 1+4=5 --1的倍數-->5 偏移 0
char b4 : 2;//b4佔2個bit位char類型
char : 4;// 佔4個bit位char類型 連續同類型 b4+4+bit5<8 共佔1個字節
char b5 : 1;//b5佔1個bit位char類型 char 1 < 8 對齊數 1 所佔字節 5+1=6 --1的倍數-->6 偏移 0
int b6 ; //b6佔32個bit位int類型 int 4 < 8 對齊數 4 所佔字節 6+4=10 --4的倍數-->12 偏移 2
}bit; //定義一個位段變量 12--最大對齊數倍數-->12 偏移 0 總大小爲 12
printf("%d\n",sizeof(bit));
bit.b1=5; // 5-->0101 僅存低2bit位 01->1
bit.b2=10; //10-->1010 僅存低3bit位 010->2
bit.b3=3; // 3-->11 僅存低4bit位 0011->3
bit.b4=2; // 2-->10 僅存低2bit位 10->2
//b2,b3共用一個字符的地址,不發生數據覆蓋
printf("%d\n",bit.b1);//%d 提升取32bit位輸出 01前補符號位0 變成1
printf("%d\n",bit.b2);//%d 提升取32bit位輸出 010前補符號位0 變成2
printf("%d\n",bit.b3);//%d 提升取32bit位輸出 010前補符號位0 變成3
printf("%d\n",bit.b4);//%d 提升取32bit位輸出 10前補符號位1 變成-2
printf("%u\n",bit.b4);//%d 提升取32bit位輸出 10前補符號位1 變成無符號類型4294967294
}
四、聯合體
1、聯合體中的成員共用一塊內存地址,存在數據覆蓋問題
2、聯合體的大小取其中最大那個
3、聯合體的聲明與定義與結構體類似
實例講解:
void combo(void)//聯合體(共用體)
{
union in //聲明一個聯合體
{
char c;
int n;
}u; //定義一個聯合體變量u
u.c='1';//'1'-->49
u.n=48; //'0'-->48 將之前的數據覆蓋
printf("%c\n",u.c);
printf("%d\n",u.n);
// 字節 高 低
u.n=0x11223344;//小端存儲 低字節存低地址
u.c=0x55; //低地址中的字節被修改
printf("%x\n",u.n);//11223355
}
五、枚舉
1、枚舉中的成員是常量值
2、枚舉中的成員若未初始化,則取默認值,第一個成員默認值爲0,往後依次加1
3、若某一成員進行了初始化,則從該成員起,往後依次加1
4、枚舉的類型爲整型類型
5、枚舉類型變量初始化時,最好使用其中的成員進行初始化
6、枚舉中的成員用 , 分開
7、枚舉的定義與聲明與結構體類似
實例講解:
{
enum Color{ //聲明一個結構體類型 類型名Color
red, //默認0
blue, //1
green=6, //6
black, //7
}color; //定義一個枚舉變量
enum Color color1=red;//定義一個枚舉變量 初始化 red
enum Color color2=black;
color1=green;
printf("%d\n",color1);
printf("%d\n",color2);
switch(color)
{
case red:
printf("紅色\n");
break;
case blue:
printf("藍色\n");
break;
default :
break;
}
}