黑马程序员——C语言基础---指针4

                                                                    ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------

十一、野指针和内存泄露

1、野指针概念 

内存好比作尺子,尺子上的0 毫米处就是内存的0 地址处,也就是NULL 地址处。这条栓“野指 针”的链子就是这个“NULL”。 定义指针变量的同时最好初始化为NULL,用完指针之后也将指针变量的值设置为NULL。也就是说 除了在使用时,别的时间都把指针“栓”到0 地址处。这样它就老实了。 

int *p;

int *p =(int *) malloc(100); //释放指针的操作

*(p+1) = 100; 

2、内存泄露 

free函数使用

定义函数:void free(void *ptr); 

函数说明:参数 ptr 为指向先前由malloc()、calloc()或realloc()所返回的内存指针。调用 free()后ptr所指的内存空间便会被收回。 假若参数ptr 所指的内存空间已被收回或是未知的内存地址,则调用free()可能会有无法预期的情况发生。若参数ptr为NULL,则free()不会有任何作用。 

其实,free函数只是将参数指针指向的内存归还给操作系统,并不会把参数指针置NULL,为了以 后访问到被操作系统重新分配后的错误数据,所以在调用free之后,通常需要手动将指针置 NULL。从另一个角度来看,内存这种底层资源都是由操作系统来管理的,而不是编译器,编译器 只是向操作系统提出申请。所以free函数是没有能力去真正的free内存的。只是告诉操作系统它 归还了内存,然后操作系统就可以修改内存分配表,以供下次分配。 

注意:free(p) 后,一定要再把 p 赋值为 NULL free(p);

p = NULL; 

否则还能继续访问指针

<span style="font-size:14px;">#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {    
    int *p1;   
    int *p = (int *)malloc(4*sizeof(int));   //16个字节
    if (p!=NULL) {        
        //申请成功做的事情
        *p = 10;
        *(p+1) = 100;
        *(p+2) = 1000;
        *(p+3) = 10000;   //存放4个整数        
    }else{
        //内存申请失败
        printf("内存申请失败!\n");        
    }    
    //应该使用free()函数释放内存空间
    //free(要释放的空间的首地址)
    free(p);
    //free(p)以后,p是一个野指针
    p = NULL;    
    *p = 100;
    printf("%d\n",*p);    
    return 0;
}</span>

十二、指针函数概念及定义 

1、指针函数概念 

前面我们介绍过,所谓函数类型是指函数返回值的类型。在C语言中允许一个函数的返回值是一 个指针(即地址),这种返回指针值的函数称为指针型函数。 

2、指针函数的定义 

定义指针型函数的一般形式为:

类型说明符 *函数名(形参表) 

/*函数体*/ 

}  

其中函数名之前加了“*”号表明这是一个指针型函数,即返回值是一个指针。类型说明符表示了 返回的指针值所指向的数据类型。

<span style="font-size:14px;">#include <stdio.h>
//返回的事两个数中大数的地址
//返回的是形参x和 y的中大数的地址
int* max(int x,int y){
    printf("max x = %p\n",&x);
    printf("max y = %p\n",&y);
    return x>y?&x:&y;
}
int *max2(int *x,int *y){
    printf("max x = %p\n",x);
    printf("max y = %p\n",y);
    return *x>*y ?x :y;
}
int main(int argc, const char * argv[]) {    
    //返回a 、b两个数中大数的地址
    int a = 3,b = 4;
    printf("a = %p\n",&a);
    printf("b = %p\n",&b);
    int *p =max2(&a,&b);
    printf("p = %p\n",p);    
    return 0;
}</span>

十三、函数指针概念及定义 

1、函数指针 

在C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址。 

我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数。 然后通过指针变量就可以找到并调用这个函数。我们把这种指向函数的指针变量称为“函数指针 变量”。  

2、函数指针定义方法 

函数指针变量定义的一般形式为:  

类型说明符 (*指针变量名)();  

其中“类型说明符”表示被指函数的返回值的类型。

“(* 指针变量名)”表示“*”后面的变量是定义的指针变量。 

最后的空括号表示指针变量所指的是一个函数。  

例如: 

int (*pf)();  

表示pf是一个指向函数入口的指针变量,该函数的返回值(函数值)是整型。 

定义一个函数的两种技巧(主要是为了方便记忆):

方法1 

1、把要指向函数头拷贝过来 

2、把函数名称使用小括号括起来 

3、在函数名称前面加上一个* 

4、修改函数名称  

方法2

1、既然是一个变量,就有变量名称 

2、既然是一个指针就要有 * 

3、如果是函数指针,就把它用小括号括起来 

4、把它将要指向的函数,函数名称的左边拷贝它左边 

5、把它将要指向的函数,名称名称的右边拷贝它右边 

6、小号后面的形参名称是可以省略的

<span style="font-size:14px;">#include <stdio.h>
float f1(int x,int y){
    return x+y;
}
int sum(int a,int b){
    return  a+b;
}
int main(int argc, const char * argv[]) {    
    int x= 3,y = 5;
    int s = sum(x, y);
    //定义函数指针
    int (*p)(int a,int b);
    //初始化函数指针
    p = sum;  //sum 函数的首地址
    //注意:定义函数指针的时候,可以不用写形参名
    int (*p1)(int ,int );
    p1 = sum;
    return 0;
}</span>

十四、函数指针使用 

1、利用函数指针调用函数 

调用函数的一般形式为:  

(*指针变量名) (实参表)  

//定义一个函数指针

int (*fun)(int *p,int len);

fun = getMax; //fun只能赋值一个函数名,并且函数有两个形参(int型指针,int型整数)

int max = fun(a,5); 

从上述程序可以看出用,函数指针变量形式调用函数的步骤如下: 

1)先定义函数指针变量,如 int (*fun)(int *p,int len); 定义 fun为函数指针变量。 2)把被调函数的入口地址(函数名)赋予该函数指针变量,如程序中 fun=getMax;  

3)用函数指针变量形式调用函数,如程序 int max=fun(a,5);  

使用函数指针变量还应注意以下两点: 

1)函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可 使指针移动指向后面或前面的数组元素,而函数指针的移动是毫无意义的。  

2)函数调用中"(*指针变量名)"的两边的括号不可少,其中的*不应该理解为求值运算,在此处它 只是一种表示符号

<span style="font-size:14px;">#include <stdio.h>
int sum(int x,int y){    
    return x+y;   
}
int jian(int x,int y){    
    return x-y;    
}
int cheng(int x,int y){    
    return x*y;   
}
int chu(int x,int y){
    return x/y;
}
int main(int argc, const char * argv[]) {   
    //函数指针的使用
    //1、定义函数指针
    int (*p)(int ,int );
    //2、给函数指针初始化
    p = sum;  //p也指向了sum函数    
    switch (3) {
        case 1:
            p = sum;
            break;
        case 2:
            p = jian;
            break;
        case 3:
            p = cheng;
            break;
        case 4:
            p = chu;
            break;
            
        default:
            break;
    }    
    //3、用函数指针间接的调用函数
    //     (*p)(23,45);
    int s = p(23,45);      
    printf("%d\n",s);   
    return 0;
}</span>

                                                                        -------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值