內存管理
自定義類型
簡單的用一個新的類型名代替原有的類型名
typedef int Integer;
int i,j;
Integer k;
//聲明結構體
typedef struct{
int month;
int day;
int year;
}Date; //用typedef 生命的結構體,原結構體變量變成了一個新的類型了
Date birthday;
Date *p;
//定義數組
typedef int Num[100];
Num a;
//定義指針
typedef char *String
String p,s[10];
//定義返回值為int類型無參數的函數指針
typedef int (*pointer)();
pointer p1,p2;
###
typedef 只是對已經存在的類型制定一個新的類型名,而沒有創造新的類型
用typedef聲明數組類型 指針類型 結構體類型 共用體類型 枚舉類型等
typedef 與 #define 表面上有相似之處
當不同的源文件中用到同一類型的數據時,常用typedef聲明一些數據類型,可以吧所有的typedef名稱聲明單獨放在一個頭文件中
使用typedef名稱有利於程序的通用與移植,有時程序會依賴與硬件的特性,用typedef類型便於移植。
------------------------------------------------------------------------
使用位域定義與結構體相仿
格式:
struct 位域結構名{
類型說明 位域名:位域長度;
}
位域長度不能超過該類型的位數
可以將該類型所占的其他位忽略
可以無位域名,表示填充或者調整位置
例如:
struct sta{
unsigned int a:4; //占用半個字節 4位
unsigned int :0; //空域 第一個字節的剩余位全清零
unsigned int b:4; //占用半個字節 4位
unsigned int c:4; //占用半個字節 4位
}
>>>>>
| a | 空 |
| b | c |
再例如:
struct stb{
int a:1; //占用1位
int :2; //表示 2個位 不用
int b:3; //占用3位
int c:2; //占用2位
}
| a 1 | 空 2 | b 3 | c 2 | //共占8個位
------------------------------------------------------------------
動態內存管理
非靜態的局部變量是分配在內存中的動態存儲區,這個存儲區是一個稱為 棧 的區域
如:int a 存放在棧區
C語言 還允許建立動態分配區域,以存放一些臨時用的數據,這些數據需要隨時開辟,不需要的時候試試釋放,這些數據是臨時存放在一個特別
的自由存儲區,成為 堆 區
如:全局變量 內存管理的手動分配單元 靜態變量都是存在 堆區
關於靜態和動態
靜態內存分配是在程序執行之前進行的,因而效率比較高,但是它缺少靈活性,要求在程序執行之前,就知道所需要的內存的類型和數量
靜態對象是有名字的變量,我們直接對起進行操作,而動態的對象是沒有名字的變量,我們通過指針間接的對他進行操作
靜態對象由編譯器自動釋放處理,動態變量需要手工釋放
方法:
malloc
calloc
free
realloc
1、malloc(大小) 分配到堆區
void * malloc(usingned int size);單位是(byte)字節數
其作用是在內容的動態存儲區分配一個長度位 side 空間,此函數是一個指針型函數,返回的指針是該分配區域的開頭的位置(或首地址)
注意指針的類型位void 即不指向任何類型的數據,只提供一個地址。放什麼類型的數據,強制轉換位什麼類型。
如果函數未能成功申請到空間(內存不足),返回空指針 NULL
如:
//分配40個字節的連續空間,讓a指向新空間的首地址
int *a =(int*)malloc(40);
//判讀是否申請成功
if(a == NULL){
}
========================
練習:申請兩個Student類型的空間
struct Student stu;
*p = (struct *Student) malloc(sizeof(struct Strdent)*2);
//判斷
if(p==NULL){
}
另一種:使用typedef
typedef struct Student{
…..
……
}stu;
stu *p = (stu*) malloc( sizeof(stu)*2 );
//判斷
if(p==NULL){
}
=========================
2、 calloc(數量,大小) 分配到堆區
viid * calloc(unsigned n,unsigned size); 上例改為 int a = sizeof(stu); stu *b = (stu*) calloc(2,a);
其作用是在內存的動態存儲區中分配n個長度位 size的連續空間,這個空間一般比較大,足以保存一個數組
可以為一維數組開辟動態存儲空間,n為數組元素個數,每個元素長度位size,這就是動態數組。
calloc ----->malloc
如:calloc(m,n) ---->malloc(m*n);
malloc ----->calloc
如:malloc(a) ---->calloc(1,a);
例如:int *a = (int*)calloc(10,sizeof(int)); if(a==NULL) 40個字節,等於分配長度為 10 的一維數組
3、free(指針變量)
void free(void *p); p=NULL;
其作用是釋放指針變量p所指向的動態空間,這部分空間能重新被其他變量使用,p應是最近一次調用calloc或malloc函數時得到的函數返回值
free(p)釋放指針變量p所指向的已分配的動態空間,但是注意,當p被釋放後,p變為野指針,所以一定要加一句 p=NULL或p=0;
free函數無返回值
動態分配的空間用完後,必須要釋放。
***** 注意 *****
在使用malloc或者cmalloc申請空間時,如 int *p = (int*)malloc(40);
p指針不允許進行 ++p 或者 --p,這樣將導致 部分內存區域無法歸還,導致內存洩露。
4、realloc(指針,大小)
void *realloc(void *p,unsigned int size);
如果已經通過malloc函數獲取到了動態的空間,想改變大小,可以使用relloc函數重新分配
用realloc 函數講p所指向動態空間的大小改為size,p的值不變,如果重新分配不成功,返回NULL( "p=(int*)relloc(p,20)" 這句話有問題,一旦重新分配不成功,p=NULL,將會導致p指向的原來的空間也無法找到,無法歸還,將導致內存洩露);