首页 > 代码库 > 指针初识

指针初识

  指针可以说是c语言从汇编那继承下来的!C语言中指针就跟汇编中的直接寻址,间接寻址等一样,去自直接操作内存;直接去操作内存,效率更高;

  指针是C语言中的精华,在C语言中很多地方都会用到指针(函数传参,函数返回值等);指针让程序员可以写出高的数据结构,编写出简洁,紧凑,高效的程序;

  所以要想熟练的使用C,指针是必不可少的;

 

  注意:在32位的操作系统中,不管定义的是什么类型的指针都是4字节;

 

1. 指针带来的一些符号的理解
  1. 星号* :
    (1)定义指针:*和前面的类型结合,定义一个该类型的指针(int *p;定义一个int类型的指针)
    (2)解引用:解引用时*p表示的是p所指向的变量;(p = &a;当操作*p时相当与操作变量a)
  2.取地址符&:
    (1)&a 表示变量a的内存地址;
    (2)取地址符使用时直接加在一个变量的前面,取地址符和变量重新构成一个新的符号,表示这个变量的内存地址(int a = 32; int *p =&a;//将a的地址赋值给p;当下次解引用p时,相当与操作变量a)

2. 指针定义并初始化,与指针定义然后赋值的区别
  1.指针定义并初始化:

1 int a = 32;2 int *p = &a;

  2.指针定义然后赋值:

1 int a = 32;2 int *p;3 p = &a;

3. 野指针的问题
  1.野指针带来的危害:
    (1)野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
    (2)野指针很可能运行时触发段错误(Sgmentation fault)
    (3)因为指针变量在定义时如果没有初始化,值是随机的。指针变量的值其实就是别的变量(指针所指向的那个变量的地址),也就意味着这个指针变量很可能指向该程序中的某一个变量的地址,当这时去解              引用这个指针时将会改变这个被指向的变量;可能导致程序发生未知的错误;

  2.怎么避免野指针    

    (1)野指针的错误来源就是指针在定义时没有初始化,也没有给赋值(也就是没有让指针指向一个可用的内存空间),然后就直接进行解引用;
    (2)明白了野指针的来源,解决方法就是:在指针的解引用之前,一起确保指针指向一个绝对可用的空间。
    (3)常规避免野指针的作法:
        1.定义指针时,同时初始化为NULL
        2.在指针使用之前,将其赋值绑定给一个可用的地址空间
        3.在指针被解引用之前,先去判断这个指针是不是NULL
        4.指针被解引用之后,将其赋值为NULL

 1 int *p = NULL;    //定义指针,并初始化为NULL 2  3 int a = 4;      //定义一个变量 4  5 p = &a;        //将a的地址与指针p绑定起来 6  7 if(NULL != p)    //指针解引用之前,判断指针是不是NULL,是不是有绑定有效的地址 8 { 9     *p = 10;       //指针p解引用10 }11 12 p = NULL;      //指针解引用后,将其赋值为NULL

 


    附件内容:为什么要将指针初始化为NULL?
      1.NULL的实质就是0,然后给指针赋初值NULL,其实就是让指针指向0地址处;
      2. 0地址处作为一个特殊的地址(我们认为指针指向0地址,就表明该指针没有被初始化,表明这是一个野指针);
      3. 0地址在一般的操作系统中都不可被访问,这也就表示当指针被指向0地址时,不会在随机的指向其它的地址,也就不会不知不觉的操作其它未知的内存地址;

 

4. const关键字与指针
  1. const修饰指针的4种形式
    1.const关键字,在C语言中用来修饰变量,表示这个变量是一个常量;
    2.const修饰指针的以下4种形式:

1       const int *p;    //表示p不是const,而p指向的变量是const(常量)2       int const *p;    //表示p不是const,而p指向的变量是const(常量)3         int * const p;    //表示p是const,而p指向的变量不是const(常量)4       const int * const p;//表示p是const,而p指向的变量也是const(常量)

    3.关于指针变量的理解,主要涉及到2个变量:第一个是指针变量p本身,第二个是p指向的那个变量(*p)。一个const关键字只能修饰一个变量,所以弄清除这4个表达式的关键就是弄清
    楚const在表达式中修饰的是哪个变量;
      1.const int *p; //const修饰的是*p(也就是p所指向的那个变量(*p))
      2.int const *p; //const修饰的是*p(也就是p所指向的那个变量(*p))
      3.int * const p; //const修饰的是p(也就是p指针变量本身)
      4.const int * const p; //前面的const修饰的是*p,后面的const修饰的是p;

5. 理解数组中a, &a, &a[0], a[0]的区别;
  例如:int a[5];


  1.a表示的是数组名,a做左值时表示的是a[5]这个数组的整个内存空间(5*4=20字节);但是C语言中规定数组操作时要独立操作,不能整个数组一起操作,所以a不能做左值;a做右
  值时,表示数组首元素(也就是a[0])的首地址,a做右值时相当于&a[0](两者的数值是一样的);


  2.&a就是数组名a取地址,就是数组的地址;&a不能做左值(&a实质是一个常量,仅仅是表示这整个数组的首地址,不是变量所以不能赋值,也就不能做左值);&a做右值时,表示整个数组
  内存空间的首地址;在数值上与a,&a[0]是一样的;


  3.&a[0]表示的是数组首元素(a[0])的首地址([]的优先级高于&,所以a先和[]结合再去地址);&a[0]是不能做左值的,&a[0]是a[0]的首地址是一个常量;做为右值时,表示的是
  a[0]的首地址;


  4.a[0]表示数组的首元素;做左值时表示a[0]对应的连续4字节空间;做右值时表示的是a[0]对应内存空间中存放的值;


  总结:
    1.&a和a做右值时的区别:&a是整个数组的首地址,而a是数组首元素的首地址。这两个在数值上是相等的,但是意义不同,意义不同会导致他们在参与运算时有不同的表现;
    2.a和&a[0]做右值时意义和数组完全相等,完全可以互相替代;
    3.&a是常量,表示整个数组内存空间的首地址,不能做左值;
    4.a做左值代表整个数组所以空间,所以不能做左值;


参考内容:朱老师物联网大讲堂













指针初识