指针的理解

       理解指针的概念

        今天要来复习的呢就是大一基本没有学过的东西,我们大一的老师可能是刚刚从国外回来,一上课就说指针没有用,了解了解就ok(想起我们的数据结构老师也是国外来的,我的意思是...),我个人觉得吧,这个东西我不知道它以后在工作或者日后的学习来说重不重要,但是就目前来说,我反正觉得这玩意算得上是重点难点!

        首先我们还是来了解一些指针是什么东西,指针最本质来理解就是地址,我觉得搬书上概念来说也讲不清楚指针到底是什么,我们通过解释一些东西来理解。

指针的类型:        

(1)int*ptr;//指针的类型是int*
(2)char*ptr;//指针的类型是char*

指针所指向的类型

(1)int*ptr; //指针所指向的类型是int
(2)char*ptr; //指针所指向的的类型是char

从上面两个东西来看是不是就可以把指针理解成为一种变量,一种地址变量!

再来接着看下面的东西:

int *p;

int a = 1;

p = &a;

//&a 的结果是一个指针,类型是int*,指向的类型是int,指向的地址是a 的地址。

这样一句话就把这个指针的类型,和它指向那个东西的类型,和它指向的是什么东西

都清楚的描述出来了(通俗一些:把a的地址放到p这个指针变量里面,p这个指针变量的类型就是int*,所指向的a的地址的类型是int,指向a的地址什么意思?就是去访问a的地址,访问a的地址什么意思?那不就是把a所储存的东西搞出来吗

        再来看下面这段代码

#include<stdio.h>
int main()
{
    int* p;
    int a = 1;
    p = &a;
    printf("%d\n",a);	
    printf("%p\n",&a);
    printf("%d\n",*p);
    printf("%p",p);
    return 0;
}
/*
1
0x7ffe1fd7bbfc
1
0x7ffe1fd7bbfc

*/

        是不是,感觉就有点好理解了,p是一个指针变量,是用来储存地址的,现在把a的地址放进去,p呢是一个指针变量,这个指针类型是int*,指向的类型是int,指向的东西是a的地址也就是&a,所以输出p就是输出a的地址,那么为什么*p的意思是指向a的地址呢?那么接下来我们来谈谈*和&这个两个东西

        *和&

        &是取地址运算符,*是间接运算符(指向)。

        我们看上面的代码,出现过两次*p,一次是在定义指针变量p的时候出现了,一次是打印*p,有什么区别呢?前面阿只是说明p这个变量是指针变量,是int*,而后面这个则代表指向指针变量p的右值,而指针变量p的右值是a的地址,也就是当我们输出*p的时候就是指向了a的地址,指向a的地址就是访问a,那不就是输出了a的值了。所以指针变量p的右值仅仅是保存了a的地址,不是直接就可以输出a的值,而是要通过*这个间接运算符去访问地址!可以看出

*p ==> * &a ==> a

*&是可以消掉的

        到这里我觉得基本的指针定义就很清楚了。

        野指针与空指针

        

  • 野指针

    野指针是一个指向未知的,不确定地方的指针.

    "未知的","不确定的" ,指向的地方可能存在,也可能不存在.

    可能可以访问,也可能不可以访问.

    对野指针的访问,会有什么后果?

    可能可以访问的,可能不可以访问(导致非法的内存访问).

    非法的内存访问 :

    不存在的地方,你去访问

    存在但不能写,你去写

    存在但不能读,你去读

    非法的内存访问 ,会导致"segmentation fault 段错误",系统把你的进程给 kill 掉.

    例子 :

    1. int *p;

      //定义了一个指针变量p,你没有赋予初始值,不代表p没有值,相反p一定会有一个值

      //意思是p一定会指向一个地方,但是这个值是多少,指向哪里,你是不知道(未定的,未知的)

      请问 p是不是一个野指针 ? A

      A 是 B 不是

    2. int *p;

      int a;

      .....

      p = &a;

      请问 p是不是一个野指针 ?B

      A 是 B 不是

               

#include<stdio.h>
int main()
{
    int* p;
    int a ;
    p = &a;
    printf("%d\n",a);	
   printf("%p\n",&a);
    printf("%d\n",*p);
    printf("%p",p);
    return 0;
}
//我们知道整型不给初始值它会默认给个0的,所以阿
//这样不会产生野指针
  • 空指针

    空指针是一个指向空(不存在的地方,NULL)的指针.

    空指针不是野指针,因为指向一个确定的地方(尽管这地方不存在).

    对空指针的访问,一定会导致 "非法的内存访问"(段错误)

    int *p = NULL;//p空指针
    ​
    *p   //用*p就会出现段错误

        指针的加减

        前面说到,指针本质上是一个地址,那么地址的加减是什么鬼呢?他这个加减呢就不是单纯的加一减一了,而是加上一个所指向类型的字节。减法同理,在做加减法运算的时候并不会改变其类型。

        

#include<stdio.h>
int main()
{
    double a;
    int *p;
    
    p = (int *)&a;
    
    printf("p = %p\n",p);
    printf("p + 1 = %p\n",p + 1);
    
    return 0;
}
/*
p = 0x7fff2df088c8
p + 1 = 0x7fff2df088cc

*/

       指针和数组

        很明显,这玩意可以与数组结合起来,因为我们前面说过了数组在开辟空间的时候是连续的开辟的,那么指针可以通过加减法来访问地址,那不就可以通过指针的加减法来遍历数组

#include<stdio.h>
int main()
{
    int a [4] = {1,2,3,4};
    printf("%d\n",*(&a[0]+1));
      for(int i = 0; i < 4;i++)
    {
        printf("%d\n",*(&a[0] + i));
    }
    return 0;
    
}

        看到第二个printf那里,是数组a的地址做加减法然后再使用了*这个间接运算符去指向,所以就可以遍历数组了。

        我们在定义一个数组的时候 int a[],a就是这个数组的数组名,这个数组名在有的时候是代表指针,有的时候是代表整个数组就以这个数组为例来看下面的总结:

        (1) 在如下情况,a代表整个数组
    sizeof(a) 求数组 a 所占的字节数,此时 a 代表整个数组
    typeof(a) 求 a 的类型 ,此时 a 代表整个数组
    &a        a的地址,此时a代表整个数组,整个数组的地址(可以通过数组的首地址来访问这个数组)
 
(2) 其他情况下,当指针用
    p = a;//a当指针用,why?  不能把整个数组赋值给其他对象.
         //a 当作指针
        p = a;==> p = &a[0];
    a + 1 ;//a当做指针用,why?整个数组不能整体 + 1
        a + 1 ==> &a[0] + 1 ==> &a[1]

反正除了(1)中提到的三种情况那就都是当指针用的

#include <stdio.h>

int main()
{
    int a[10] = {0,1,2,3,4,5,6,7,8,9};

     printf("%ld\n",sizeof(a));//sizeof(a) a此时代表整个数组,
                             //sizeof(a) 求整个数组所占的字节数
     printf("%p\n",a);//此时a当做指针来用,a ==> &a[0]
     printf("%p\n",&a[0]);
     printf("%d\n",*a);//不是三种情况之一,所以当指针用,指向第一个数

    printf("%d\n",*(a + 1));
                //*(&a[0] + 1)==>*(&a[1]) ==> a[1]

    return 0;
}

        

        

        

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值