首页 > 代码库 > 第八天:C基础之内存分配与函数指针

第八天:C基础之内存分配与函数指针

  虚拟内存自上而下分为 堆栈段,数据段,代码段 , 堆栈段分为堆区和栈区 ,栈区从上往下分配内存,堆区从下往上分配内存 。数据段分为静态区和全局区。两者的作用域不同。代码段分为只读区和代码区 。最后还有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基础之内存分配与函数指针