標籤:style blog color io 使用 ar sp 資料 div
虛擬記憶體自上而下分為 堆棧段,資料區段,程式碼片段 , 堆棧段分為堆區和棧區 ,棧區從上往下分配記憶體,堆區從下往上分配記憶體 。資料區段分為靜態區和全域區。兩者的範圍不同。程式碼片段分為唯讀區和代碼區 。最後還有bss區現在還不涉及。
六個地區的定義如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int number = 200; 5 6 int hello() 7 { 8 static int s = 400; 9 int n = 100;10 char *p = malloc(10);11 char *m = "hello world";12 printf("stack is %p\n", &n);13 printf("global is %p\n", &number);14 printf("static is %p\n", &s);15 printf("heap is %p\n", p);16 printf("read only is %p\n", m);17 }18 19 int main()20 {21 int i = 10;22 hello();23 }
這幾天的的C基礎培訓都離不開記憶體配置圖。這個也許是在學校學習譚大爺的C語言最大的區別吧。知道程式碼在記憶體中的分布,畫出程式在運行中的記憶體配置圖,對於程式的理解是非常有協助的,比如今天講的函數指標。
函數名代表函數的首地址,這樣的話,我們就可以通過函數指標來調用函數 。如定義了函數hello(); 函數指標為int (*fp)() = hello; 這時候使用hello的地方都可以用fp來代替了。當然 ,函數指標也能作為函數的參數。我們稱參數中帶有函數指標的函數叫做回呼函數, 函數指標也夠在結構體中定義 。下面的函數就是通過函數指標,回呼函數,結構體三種方式調用函數。
1 #include<stdio.h> 2 3 struct person{ 4 char *name; 5 int (*fp)(char *); 6 int (*fd)(struct person); 7 }; 8 9 int hello(char *s)10 {11 printf("my name is %s\n",s);12 }13 int pson(struct person jack)14 {15 printf("jack is name is %s\n",jack.name);16 17 }18 int main()19 {20 struct person tom;21 tom.name = "tom";22 tom.fp = hello;23 tom.fp(tom.name);24 struct person jack;25 jack.name = "jack";26 tom.fd = pson;27 tom.fd(jack);28 29 30 }
回呼函數也是函數,也可以繼續被回調。於是乎有了下面的代碼:
1 #include<stdio.h> 2 3 int func(int i) 4 { 5 printf("i is %d\n",i); 6 } 7 int call(int (*fp)(int),int i) 8 { 9 fp(i);10 11 }12 int recall(int (*fd)(int (*)(int),int ),int (*fp)(int),int i)13 {14 fd(fp,i); 15 }16 17 int main()18 { 19 int (*fp)(int);20 fp = func;21 call(fp,10);22 int (*fd)( int (*)(int),int) = call;23 recall(fd,fp,20);24 }
12行的回調再回呼函數的參數會讓人看暈的。。。 但是,這時候萬能的記憶體配置圖來了。畫個圖,問題就能解決。
老劉看我們被函數指標繞的迷糊。下午的時候就講了linux的基礎命令。 lsusb ,lspci 查看裝置 tftp 的配置。這些就不寫了。
第八天:C基礎之記憶體配置與函數指標