C語言之結構體 共用體 列舉 typedef
阿新 • • 發佈:2018-11-15
結構體型別和結構體變數, struct
定義結構體型別時 不佔記憶體
匿名結構體,無法建立變數訪問,有限的結構體型別變數
結構體變數不能整體引用,只能引用變數成員
結構體變數用大括號賦值,只有在建立並初始化的時候才可以
同一型別的結構體變數之間可以直接互相賦值,結構體型別定義的時候,不可以賦初值
字串不能直接賦值
結構體內部再定義一個結構體,沒有建立結構體的例項,
再次定義的結構體內部的變數,會被當作母結構體的成員變數
結構體內部再定義一個結構體,建立結構體變數,該變數會直接作為一個成員
結構體陣列在記憶體中是連續排列的
結構體 共用體 所佔記憶體大小一定大於等於所有的成員的位元組之和,準則3:
1、結構體變數大小能夠被最寬基本型別成員的大小所整除
2、結構體每個成員相對於結構體首地址的偏移量都是成員的大小的整數倍,如有需要編譯器會在成員之間填充位元組
3、結構體的總大小為結構體最寬基本型別大小的整數倍,如有需要編譯器會在最末一個成員之後加上填充位元組
記憶體大小和成員的位置順序有也關係
結構體可以巢狀共用體,也可以在內部定義共用體
共用體 union
共用體變數任何時刻只有一個成員存在,共用體變數在分配記憶體時,長度等於最長成員所佔的位元組
共用體大小必須包含最大的成員資料,可以整除最小的成員資料,記憶體對齊機制
共用體大括號初始化的時候只能初始化第一個成員,共用體變數可以直接賦值
共用體和結構體的差別,在於記憶體的機制不同,共用體任何時刻只有一個成員,結構體所有成員均存在,共用體用大括號初始化的時候只能對第一個成語初始化
用法和結構體類似
列舉型別 enum
列舉了所有的情況,用列舉型別宣告變數時,只能取集合中的某項作為值,一定程度保證了取值的安全性
型別取別名 typedef 方便程式的移植
typedef unsigned int uint
typedef 沒有建立資料型別,給已經有的資料型別起別名僅僅適用於型別,編譯的時候處理
型別定義可以巢狀
typedef 步驟:
1、按照定義變數的方式寫出定義體 如 int i;
2、將變數名換成新型別名 如 int INTEFER;
3、最前面加typedef 如 typedef int INTEGER;
4、用新型別名定義變數 如 INTEGER i,j;
#define uint unsigned int 適用任何場合,預處理
深拷貝 複製記憶體地址的內容
淺拷貝 共享記憶體地址
位元組對齊規則
定義結構體型別時 不佔記憶體
匿名結構體,無法建立變數訪問,有限的結構體型別變數
結構體變數不能整體引用,只能引用變數成員
結構體變數用大括號賦值,只有在建立並初始化的時候才可以
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h> //結構體變數定義形式一 struct nameinfo //宣告結構體型別,,不分配記憶體 { char name[50]; char phone[50]; int num; int nameinfo; //成員名和型別名可以重名 }; //struct nameinfo zqh; //宣告結構體變數 //結構體變數定義形式二 //#define info struct nameinfo //info //宣告結構體型別 //{ // char name[50]; // char phone[50]; // int num; //}; //info zqh; //宣告結構體變數 //結構體變數定義形式三 //struct nameinfo //宣告結構體型別 //{ // char name[50]; // char phone[50]; // int num; //} zqh; //宣告結構體變數 int main() { struct nameinfo zqh = {"梵高先生","1506051****",2018}; //宣告結構體變數 //結構體變數用大括號賦值, //只有在建立並初始化的時候才可以 //zqh.num = 2018; //strcpy(zqh.name,"梵高先生"); //字串不可以賦值號賦值 //sprintf(zqh.phone,"1506051****"); //字串變數賦值的兩種方式 printf("%d %s %s\n", zqh.num, zqh.name, zqh.phone); //struct nameinfo qh = zqh; //同一型別的結構體變數之間可以直接互相賦值 //printf("%d %s %s\n", qh.num, qh.name, qh.phone); system("pause"); }
同一型別的結構體變數之間可以直接互相賦值,結構體型別定義的時候,不可以賦初值
字串不能直接賦值
結構體內部再定義一個結構體,沒有建立結構體的例項,
再次定義的結構體內部的變數,會被當作母結構體的成員變數
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h> struct YouStruct { char phone[15]; char addr[15]; }; struct MyStruct { int year; char name[20]; struct YouStruct you; //結構體巢狀 }; int main() { struct MyStruct num[10]; //定義結構體陣列,同定義結構體變數3種形式 struct MyStruct zqh; //初始化方式1 strcpy(zqh.name, "梵高先生"); zqh.year = 22; strcpy(zqh.you.addr , "平和縣"); //結構體巢狀訪問 sprintf(zqh.you.phone, "1506051****"); printf("%s %d %s %s\n",zqh.name,zqh.year,zqh.you.addr,zqh.you.phone); //初始化方式2 struct MyStruct zzz = { 22, "董卓瑤", { "15*********", "南京" } }; printf("%s %d %s %s\n", zzz.name, zzz.year,zzz.you.addr, zzz.you.phone); system("pause"); }
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> struct mystruct { int num; char uct[20]; }; int main() { struct mystruct my; //定義結構體變數 my.num = 2351; strcpy(my.uct, "梵高先生"); printf("my.uct=%d my.uct = %s\n",my.num,my.uct); struct mystruct *p = &my; //定義結構體指標,並初始化 printf("%p\n",p); //指標訪問結構體方式一 (*p).num = 1990; sprintf((*p).uct,"你好,明天"); printf("(*p).num=%d (*p).uct=%s\n", (*p).num, (*p).uct); //指標訪問結構體方式二 p->num = 3195; strcpy(p->uct,"熱河"); printf(" p->num=%d p->uct=%s\n", p->num, p->uct); system("pause"); }
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct mystruct
{
int num;
char uct[20];
};
//結構體函式引數傳遞也有副本機制,使用結構體作為引數,很浪費記憶體,不能修改函式外部的資料
//用指標可以修改函式外部的資料
void changes(struct mystruct *p)
{
p->num = 200300;
}
int main()
{
struct mystruct my ; //定義結構體變數
struct mystruct *p; //指向結構體陣列的指標
p = &my; //初始化指標
p->num = 100200;
strcpy(p->uct, "梵高先生");
printf("%d %s\n",p->num,p->uct);
changes(p);
printf("%d %s\n", p->num, p->uct);
system("pause");
}
結構體內部再定義一個結構體,建立結構體變數,該變數會直接作為一個成員
結構體陣列在記憶體中是連續排列的
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct mystruct
{
int num;
char uct[20];
};
int main()
{
struct mystruct my[5] = //定義結構體陣列
{
{100200,"梵高先生"},
{200300,"下雨"},
{300400,"山陰路的夏天"},
{400500,"關於鄭州的記憶"},
{500600,"杭州"}
};
struct mystruct *p ; //指向結構體陣列的指標
p = my; //初始化指標
for (struct mystruct *pa = p; pa < p+5; pa++)//指標遍歷結構體陣列
{
printf("%d %s\n",pa->num,pa->uct);
}
system("pause");
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct mystruct
{
int num;
char uct[20];
};
int main()
{
struct mystruct *p = (struct mystruct *)malloc(sizeof(struct mystruct)*5);
//分配記憶體
int num = 100200;
char str[5][20] = { "梵高先生", "下雨" , "山陰路的夏天" ,"關於鄭州的記憶" , "杭州" };
char (*pstr)[20] = str;
//建立一個指標儲存二維陣列的首地址,一個指向有20個元素的一維陣列的指標
for (struct mystruct * pa = p; pa < p + 5; pa++) //寫資料
{
pa->num = num;
strcpy(pa->uct, pstr);
num += 100100;
pstr ++;
}
for (struct mystruct * pa = p; pa < p + 5; pa++) //讀資料
printf("%d %s\n", pa->num, pa->uct);
free(p); //釋放記憶體
system("pause");
}
結構體 共用體 所佔記憶體大小一定大於等於所有的成員的位元組之和,準則3:
1、結構體變數大小能夠被最寬基本型別成員的大小所整除
2、結構體每個成員相對於結構體首地址的偏移量都是成員的大小的整數倍,如有需要編譯器會在成員之間填充位元組
3、結構體的總大小為結構體最寬基本型別大小的整數倍,如有需要編譯器會在最末一個成員之後加上填充位元組
記憶體大小和成員的位置順序有也關係
結構體可以巢狀共用體,也可以在內部定義共用體
共用體 union
共用體變數任何時刻只有一個成員存在,共用體變數在分配記憶體時,長度等於最長成員所佔的位元組
共用體大小必須包含最大的成員資料,可以整除最小的成員資料,記憶體對齊機制
共用體大括號初始化的時候只能初始化第一個成員,共用體變數可以直接賦值
共用體和結構體的差別,在於記憶體的機制不同,共用體任何時刻只有一個成員,結構體所有成員均存在,共用體用大括號初始化的時候只能對第一個成語初始化
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//任意時刻只有一個成員存在
//共用體大小必須包含最大的成員資料,可以整除最小的成員資料,記憶體機制
union info //共用體和結構體類似,
{
int u32;
float f32;
char str[9];
};
int main()
{
union info num;
union info *p = #
union info num1 = num; //共用體可以直接賦值
//共用體大括號初始化的時候只能初始化第一個成員
num.u32 = 15;
num.f32 = 12.7;
strcpy(num.str, "梵高先生");
printf("%d %f %s\n",num.u32,num.f32,num.str);
//最後的結果取決於最後的賦值
printf("%d %f %s\n", p->u32,p->f32, p->str);
//以指標的方式引用
printf("所佔位元組%d\n", sizeof(num));
system("pause");
}
用法和結構體類似
列舉型別 enum
列舉了所有的情況,用列舉型別宣告變數時,只能取集合中的某項作為值,一定程度保證了取值的安全性
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
enum level //定義列舉型別
{
T1 = 8,T2,T3,T4 = 8,T5,T6,T7,T8,T9,T10
};
int main()
{
//列舉型變數,可以將資料限定在一定範圍之內
//刨除多餘資料
enum level num = T8; //宣告列舉型別變數
printf("%d\n",T1); //如果沒有指定初值的值預設編號從0開始依次增大
printf("%d\n", T2);
printf("%d\n", T3);
printf("%d\n", T4);
printf("%d\n", T5);
system("pause");
}
型別取別名 typedef 方便程式的移植
typedef unsigned int uint
typedef 沒有建立資料型別,給已經有的資料型別起別名僅僅適用於型別,編譯的時候處理
型別定義可以巢狀
typedef 步驟:
1、按照定義變數的方式寫出定義體 如 int i;
2、將變數名換成新型別名 如 int INTEFER;
3、最前面加typedef 如 typedef int INTEGER;
4、用新型別名定義變數 如 INTEGER i,j;
#define uint unsigned int 適用任何場合,預處理
深拷貝 複製記憶體地址的內容
淺拷貝 共享記憶體地址
位元組對齊規則