一、記憶體映像
在運行程式時,系統會自動的映射一塊虛擬記憶體,應用程式就是在這樣的虛擬記憶體空間中啟動並執行,如下:
二、儲存類型
C語言中,定義變數或者數組時,都會對該變數或者數組的屬性進行說明,比如,int a;//int在這裡說明變數a:1)在記憶體中的長度,2)資料在記憶體中的儲存方式
如果我們還想知道變數a的其他屬性,比如:在記憶體中的位置,佔用記憶體的時間段,在程式中的使用範圍,此時,這些屬性就是由變數a的儲存類型決定的,那麼一個變數的儲存類型是什麼。
在C語言中儲存類型分為以下6中:
儲存類型 定義的位置定義的形式 在記憶體中的位置佔用記憶體的時間段(生存期/儲存期) 在程式中的使用範圍(範圍)
1)自動儲存類型 代碼塊內 int a; 棧 定義--->代碼塊執行結束 代碼塊內
2)寄存器才儲存類型 代碼塊內register int a; 寄存器/棧定義--->代碼塊執行結束 代碼塊內
3) 全域非static靜態儲存類型 代碼塊外int a; .data/.bss定義--->程式結束 多檔案
4)全域static靜態儲存類型 代碼塊外static int a; .data/.bss定義--->程式結束 單檔案
5)局部static靜態儲存類型 代碼塊內static int a; .data/.bss定義--->程式結束 代碼塊內
6)外部儲存類型 代碼塊外 extern int a; .data/.bss定義--->程式結束 多檔案
函數原型範圍:
指的是在函數原型聲明語句中定義的變數,該變數具有函數原型範圍。例如:
#include <stdio.h>void fun1(int ,int a[]); //函數原型聲明void fun2(int ,int m, int a[][m]); //函數的原型聲明,該聲明語句中的m,具有函數原型範圍int main(void){//int a[5] = {1,2,3,4,5};int a[2][3] = {{1,2,3},{4,5,6}};fun2(2,3,a);return 0;}void fun1(int n,int a[n]){int i;for(i = 0; i < n ; i++)printf("%d\t",a[i]);printf("\n");}void fun2(int n,int m, int a[n][m]){int i,j;for(i = 0; i < n; i++){for(j = 0; j < m; j++)printf("%d\t",a[i][j]);printf("\n");}}
三、記憶體管理
1、堆與棧的特點
1》棧特點:
1)執行效率高
2)空間相對比較小
3)有名空間
4)由系統分配和釋放空間
5)生存期短,範圍小
2》堆特點:
1)執行效率較低
2)空間相對較大
3)無名空間
4)由軟體工程師自己申請和釋放空間
5)生存期有軟體工程師自己決定,範圍一般是整個程式
2、堆空間的使用
1》申請空間
void *malloc(size_t size);
參數size:表示要申請的空間大小
傳回值類型void* :申請成功時,malloc函數返回的空間的起始地址,該地址需要強制類型轉換才可以使用,申請失敗時,返回NULL
注意:
1)申請的空間是連續的
2)空間沒有初始化
3)對空間為無名空間,所有要使用,必須通過指標訪問。
例如1:
#include <stdio.h>#include <stdlib.h>int main(void){int *p;p = (int*)malloc(sizeof(int));if(p == NULL){printf("malloc failed!\n");exit(1); //退出當前程式}*p = 100;printf("*p = %d\n",*p);return 0;}
例如2:
#include <stdio.h>#include <stdlib.h>int main(void){int a[5] = {1,2,3,4,5};int *p,i;//p = a;p = (int*)malloc(5*sizeof(int));if(p == NULL){printf("malloc failed!\n");exit(1); //退出當前程式}for(i = 0; i < 5; i++)p[i] = i+1;for(i = 0; i < 5; i++)printf("%d\t",*(p+i));printf("\n");return 0;}
void *calloc(size_t nmemb, size_t size);
參數:nmemb 表示資料個數
參數:size 表示資料大小
傳回值與malloc一致,例如:
#include <stdio.h>#include <stdlib.h>int main(void){int a[5] = {1,2,3,4,5};int *p,i;//p = a;p = (int*)calloc(5,sizeof(int));if(p == NULL){printf("malloc failed!\n");exit(1); //退出當前程式}for(i = 0; i < 5; i++)p[i] = i+1;for(i = 0; i < 5; i++)printf("%d\t",*(p+i));printf("\n");return 0;}
calloc申請的空間會初始化
void *realloc(void *ptr, size_t size); //該函數功能:對申請的堆空間進行擴充
參數:ptr 表示之前申請的堆空間的起始地址
參數:size 表示擴充之後的空間的總大小
傳回值:成功表示擴充之後的空間的起始地址,失敗返回NULL
2》釋放空間
void free(void *ptr);
參數:ptr 表示申請到的堆空間的起始地址
注意:
不要給free傳NULL指標
不要釋放申請的空間的一部分
例1:
#include <stdio.h>#include <stdlib.h>int main(void){int *p,*t,i;//p = a;p = (int*)malloc(5*sizeof(int));if(p == NULL){printf("malloc failed!\n");exit(1); //退出當前程式}t = p;for(i = 0; i < 5; i++)p[i] = i+1;for(i = 0; i < 5; i++)printf("%d\t",*p++);printf("\n");//free(NULL); //沒有意義//free(p); //此時p存放的不是malloc返回的地址free(t);return 0;}
例2:
#include <stdio.h>#include <stdlib.h>int main(void){int *P; //*P = 100; //P為野指標int *p,*t,i;//p = a;p = (int*)malloc(5*sizeof(int));if(p == NULL){printf("malloc failed!\n");exit(1); //退出當前程式}t = p;for(i = 0; i < 5; i++)p[i] = i+1;for(i = 0; i < 5; i++)printf("%d\t",*p++);printf("\n");//*p = 200; //非法操作//free(NULL); //沒有意義//free(p); //此時p存放的不是malloc返回的地址free(t);t == NULL;//*t = 200; //非法操作return 0;}
四、static關鍵字
有三個作用:
1、修飾全域變數:
改變全域變數的範圍:多檔案範圍變為單檔案範圍
2、修飾局部變數:
改變局部變數的生存期:延長了變數的生存期,使得變數在程式結束時才釋放空間
3、修飾函數:
改變函數的連結類型:外部連結變為內部連結
五、進階聲明
1、聲明和定義
1》聲明
1)告訴系統變數或者函數此刻需要使用,它的定義在其他地方
2)在程式中可以對變數或者函數多次聲明
2》定義
1)告訴系統給該變數分配適當大小的空間
2)在程式一個變數只能定義一次
3)定義語句可以當作特殊的聲明
2、typedef關鍵字
給一個已有的類型引入一個新的名字
六、位元組序
1、概念:位元組序指的是處理器在對字取值時,解釋其中各個位元組的順序。
2、小端序(big-endian):
最高有效位所在的位元組放在最高位元組位置上,其他位元組依次放在低位元組位置上,則該位元組序稱為高位優先(即小端序)。
3、大端序(little-endian):
最低有效位所在的位元組放在最高位元組位置上,其他位元組依次放在低位元組位置上,則該位元組序稱為低位優先(即大端序)。
4、判斷機器的位元組序
#include <stdio.h>int main(void){unsigned int word = 0x12345678;unsigned char byte = *(char*)&word;printf("byte = %hhx\n",byte);if(byte == 0x12)printf("大端序!\n");elseprintf("小端序!\n");return 0;}