C语言———指针(二)

三、野指针

3.1什么是野指针

野指针:就是指针指向的位置是不可知(随机性,不正确性,没有明确限制的)。

3.2野指针的形成原因

3.2.1、指针未初始化

**指针变量在定义时不会自动初始化,如果未初始化,而是随机的一个值。此时操作指针。指针就是去访问一个不确定的地址,所以结果是不可知的。此时该指针成为野指针。

**解决方案:在定义指针时,要么将其初始化为一个合理的地址,要么初始化为NULL。

#include<stdio.h>
int main()
{//野指针
int* p;//就是野指针  
// printf("%d\n",*p); // 未初化,直接用  错误的   因为是随之机值的空间,内存可能被其它占用了。
*p = 10;
--------------------------
int a = 10;
int* p;
  p=a;  // 也是错误的
//p = &a;
//*p = 100;
printf("%d\n", a);
return 0; 
    
}

 3.2.2、指针越界访问

#include<stdio.h>
int main()
{
    int arr[10] = { 1,2,3 };
    int i = 0;
    int* p = arr;
    for (i = 0; i <= 10; i++)
    {
      *p = i;   //i=10时越界
         printf("%d\n", arr[i]);//越界访问会出现一个随机值
    }
    return 0;
}

//修改

    int arr[10] = { 1,2,3,4,5,6,7,8,9 };
        int* p1 = arr;

        for (int i = 0; i < 10; i++) {
    printf("%d\n", *(p1 + i));
    printf("%d\n", arr[i]);
}
    return 0;
}
 

 3.2.3、指针指向空间的释放后位置为NULL

**在使用free或delete释放内存后,指针指向的内存被销毁,空间被释放,但指针的值并未改变,仍然指向这块内存。

**解决方案:在调用free或delete之后,应立即将该指针置为NULL,以避免成为野指针。

#include<stdio.h>
int* test()
{
    int a = 10;
    return &a;          //&a=0x0012ff40  返回变量a的地址
}

int main()
{
    int* p = test();// p就是一个野指针
    return 0;
}

//当 test 函数执行完毕后,局部变量 a 的内存空间会被释放,但指针 p 仍然指向这块已经释放的内存区域。此时,p 就成了一个“野指针”

//修改
int* test()  
{  
    static int a = 10; // 静态变量   全局都可用
    return &a;  
}
//或
int* test()  
{  
    int* a = (int *)malloc(sizeof(int)); // 动态分配内存  
    if (a == NULL) {  
        // 处理内存分配失败的情况  
        return NULL;  
    }  
    *a = 10;  
    return a;  
}  
  
// 在 main 函数或其他地方使用完毕后,记得释放内存  
free(p);

3.3避免野指针的方法:

1.指针初始化

int *p=NULL;

赋值为NIULL值得指针称为空指针,NULL指针是一个定位在标准库<stdio.h>中的值为零常量

#defined NULL 0

2.小心指针越界

3.指针指向空间释放及时置NULL

int a=10;
int *pa=&a;
printf("%d\n",*pa);
pa=NULL;     //把pa指针置成NULL

4.避免返回局部变量的地址

5.指针使用之前检查有效性 

四、指针和数组

"*",也称为解引用符号,其作用与&相反。

"*",后面只能跟指针(即地址)或指针变量,“&”后面跟的是普通变量(包括指针变量)。

 

 

4.1一维数组与指针

4.1.1指向一维数组的指针变量

所谓数组元素的指针就是数组元素的地址,可以用一个指针变量指向一个数组元素。

int a[10]={2.4,6,8,10,12,14,16,18,20};
int *p;//定义p为指向整型变量的指针变量
p=&a[0];// 把a[0]元素的对应地址赋值给指针变量p

int *q;
q=a;//理解:  a[0]的地址赋给q
printf("%p",p);
printf("%p",q);

 如下几个写法是等价的:

int *p;

p=&a[a];            //千万不要写成*p=&a[0];那就错了

int *p=&a[0];

int *p=a;         //a不代表整个数组,所以这里不是将数组a赋值给p,而是代表数组元素a[0]的首地址

注意:因为数给名a保存的是数组首元素a[0]的地址,所以scanf函数中的输入项如果是数组名,不要再加地址符&。

 //复习一下scanf()      int a;    &a  
     char arr1[10];
       scanf("%s", arr1);//此时arr前不需要添加&
        puts(arr1);

 4.1.2使用指针访问数组的元素

如果指针变量p的初值为&a[0]则:

p+i和a+i 就是数组元素a[i]的地址。 或者说,它们指向a数组序号为i的元素。

*(p+i) 或 *(a+i) 是 p+i 或 a+i所指向的数组元素的值,即a[i]的值。

规律:

int a[10]={1,2,3,4,5};

int *p=&a[0];

a[0]: 表示 a[0]的数据值

a[0]的地址:&a[0]、p、a

a[0]的数据值:a[0]、*p,*a;

a[i]: 表示a[i]的数据值

a[i]的地址: &a[i]、p+i 、a+i;

a[i]的数据值:a[i] 、*(p+i)、*(a+i)

数组名字是数组的首元素地址,但它是一个常量   ******

*和[]效果一样,都是操作指针所指向的内存 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值