| 本帖最后由 稳稳の幸福 于 2017-4-27 20:13 编辑 
 程序中的栈和堆
 函数参数指针传递程序帧是支持函数执行的内存区域,与堆共享内存区域栈在程序帧下部,由下往上增长;堆在上部,由上往下增长栈存放函数参数和局部变量,堆管理动态内存栈帧保存以下元素
 
 [size=0.85em]void allocateArray(int *arr, int size, int value){    arr=(int *)malloc(size * sizeof(int));    for(i=0;i<size;++i)        *(arr+i)=value;}int *vector = NULL;allocateArray(&vector,10,1);函数参数传递时,实参传递给形参的是值传递,这会复制实参,不够高效,尤其是传递结构体时,我们不希望再一次复制完全的结构体。而使用指针传递,不但可以改变实参,还能更高效的传递参数。如传递结构体时,传递结构体指针即可,无需其他消耗。如果传递时,使用指向常量的指针,则可以更高效的获取实参内容,而且不会改变实参内容。传递指针的指针对于以下代码
 
 会产生问题 首先函数内部虽然将地址传给了[size=0.85em]arr,但是紧接着[size=0.85em]arr的地址被重新通过[size=0.85em]malloc赋值,所以并没有使用[size=0.85em]vector的内容函数释放后,分配的空间地址丢失,导致内存泄漏
 
 为了解决以上的问题,我们使用指向指针的指针。[td] | 想改变的实参类型 | 形参形参的形式 |  | int | int * |  | int * | int ** | 
 当函数改变的实参的值时,而不是形参创建的副本,那么函数传递就要传递实参的地址当函数要改变的是实参本身就是指针,那么函数就要传递指针的地址,也就是函数的形参要定义成指向指针的指针。
 
 所以修改代码[size=0.85em]void allocateArray(int **arr, int size, int value){    *arr=(int *)malloc(size * sizeof(int));    for(i=0;i<size;++i)        *(*arr+i)=value;}int *vector = NULL;allocateArray(&vector,10,1); 这样调用,函数内部分配的内存地址会直接传递给实参vector,不会导致地址的丢失等问题函数返回指针 [size=0.85em]int * allocateArray(int size, int value){    int *arr = malloc(size * sizeof(int));    for(int i=0;i<size;++i)        *(arr+i)=value;    return arr;}声明[size=0.85em]int * fcuntion()即意味着此函数返回的是一个整型指针。[size=0.85em]注意与int (*fcuntion)()的区别常用的函数返回指针技术常用的返回指针技术有两种:函数内部使用[size=0.85em]malloc分配内存空间。调用者负责释放内存
 
 然后使用以下方式调用int *vector = allocateArray(10,1);for(i=0;i<10;++i)    printf("%p",*(vector+i)); free(vector);最后要注意一定要释放内存,因为函数内部只负责了分配内存,要由调用者负责释放
 int * allocateArray(int *arr, int size, int value){   if(arr != NULL)    {        for(int i=0;i<size;++i)            *(arr+i)=value;    }    return arr;}函数内部只负责修改传递过来的指针并修改它,内存的分配和释放都有调用者负责。对于传递过来的指针,优先判断是否为空是个好习惯。如下例:
 
 然后使用以下方式调用[size=0.85em]int* vector=(int *)malloc(size * sizeof(int));allocateArray(vector,10,1); 函数返回指针注意的问题书中说此方法不推荐,目前不知道为什么 以上两种方式,函数内部使用的内存都是处于堆区域,所以即使函数结束,弹出栈,堆区域的内容仍然存在,只要保留地址即可。但是函数返回指针不要返回函数内部定义的变量,这样函数结束弹出栈帧以后,变量立即消失,这样就出现问题
 函数返回指针要注意四个事项: 返回未初始化的指针返回指向无效地址的指针返回局部变量指针返回指针但是外部调用没有释放
 
 在处理函数返回指针时,一定要根据内存方式注意以上四项。完善的free函数 内置free()函数存在以下问题: void safeFree(void **p){    if(p != NULL && *P != NULL){        free(*p);        *p =NULL;    }}不会检查传入指针是否为空释放后不会将指针置为NULL 这时候可以创建自己的free函数
 
 其中void指针意味着可以传入任何指针类型,定义**p是因为释放的本身是个指针,需要使用传递指针的指针来真正操作指针。 更快的方式可以定义一个宏 #define safeFree(p) safeFree(void ** (&p)) 配合safeFree函数使用。函数指针 typedef int (* fptrOperation)(int ,int);int sum(int a, int b){ return a+b}int sub(int a, int b){ return a-b}int computer(fptrOperation operaton, int num1, int num 2) { return operaton(num1, num2) }printf("%d\n",computer(sum,1,2));printf("%d\n",computer(sub,5,3));函数指针定义的方式就是 [size=0.85em]int (*function)(),这时候[size=0.85em]function就作为一个指针指向了函数的地址。函数指针对性能是有一定影响的,使用它处理器就无法配合流水分支预测正常的函数声明中[size=0.85em]int func(),函数名[size=0.85em]func没有明确定义是指针,还是其他类型。但是对打印函数名[size=0.85em]func的地址,或者函数名取值后[size=0.85em]&func的地址都是同一个值。所以我们只要知道正常的函数声明中,函数名可以等效为该函数的地址。对于函数指针,建议使用[size=0.85em]fptr作为前缀使用了函数指针,使用该指针调用函数,程序将不检查参数传递的是否正确为函数指针声明一个类型定义会比较方便[size=0.85em]typedef int (*fptrfunc)(int,int)函数指针可以实现在函数调用中动态的调用其他函数,实现了函数作为参数的传递,这样可以使用C语言进行函数式编程。个人感觉函数指针是实现C++的某种基础。例如以下代码
 
 fptrOperation operaton[10]={NULL};返回函数指针即用函数指针去声明一个函数,例[size=0.85em]fptrOperation switchcode(char opecode)当用函数指针去声明一个数组时,那么数组中的每个元素,都代表函数指针指向的一个函数操作,大大增加了函数调用的丰富性。例如
 
 
 |