zoukankan      html  css  js  c++  java
  • 指针之——一级二级多级指针

    指针,C语言永恒的话题。关于指针,在《c和指针》上是这样形容的,指针就是地址的另外一个叫法。所以我们要明白,指针和指针变量的区别,指针就是地址,指针变量是存放指针的变量,即指针变量存放的是地址,我们通过间接访问符可以得到该地址的内容。但是,在一般情况下,我们都把指针变量说成指针这样的简称。例如:void (*fuc)(int a);我们会说fuc是一个指针,指向一个参数为int返回值为void的函数。这个时候我们并不它称作指针变量,而笼统地称为指针,因为我们使用指针的情况下,大多是在操作指针变量,但是,在某些情况下,需要精确表述时,应该明白,指针变量是存放地址(指针)的,指针就是一个地址。后面所说的指针,不特殊说明,都指指针变量,因为指针和指针变量大部分时候我们不是去区分它的文字定义,而是怎么去使用它,最主要是因为这已经三人成虎了。比如,char *p=NULL;我们都说p是一个指针,其实严格来说这个p是指针变量。因为定义一个指针类型的变量,必然在内存中开辟了空间,就是指针变量了,但已经被大家都这样叫指针了,所以,虽然我们这样叫着,但具体含义还是要清楚的。我们使用赋值方式给一个“指针”的时候,这个指针一定已经是指针变量了,因为地址不能做左值,地址对应的内存空间才可以。不过始终得有个约定吧,所以就先统称指针了。

    指针就是为间接赋值或者说间接改变某些东西存在的。

    eg:

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<stdio.h>  
     3 
     4 int main()
     5 {
     6     int a = 10;
     7     int *p1= NULL;
     8     int **p2 = NULL;
     9 
    10     //直接修改方式
    11     a = 20;
    12     printf("a:%d
    ", a);
    13     //一级间接修改
    14     p1 = &a;
    15     *p1 = 30;
    16     printf("a:%d
    ", a);
    17     //二级间接修改
    18     p2 = &p1;
    19     //*p2 = 0x11;//可能会出错,因为内存中这片区域不一定可以使用
    20     **p2 = 40;//这样二级间接修改a就不会出错
    21     printf("a:%d
    ", a);
    22     return 0;
    23 }

    可能在这里你会觉得,既然一级指针就已经能够更改一个地址的变量了,为什么还要二级指针或者多级指针呢?

    一级指针用普通变量的地址去接,二级指针用一级指针的地址去接,N级指针用N-1级指针的地址去接。

    我们在一个程序中已经使用了一级指针了,如果我们想修改这个一级指针或者这个一级指针指向的内容,就会使用到二级指针了,但是,为了代码的可读性,最好用二级以下的指针解决。

    指针变量需要指向一个内存空间,内存空间相当于门牌号,而对一个指针解引用(*),相当于间接访问这个指针变量中存储的地址里面对应的内容,(*)相当于一把钥匙打开了房门。

    eg:

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<stdio.h>  
     3 
     4 int main()
     5 {
     6     int *p1;
     7     int **p2;
     8 
     9     p1 = 0x325;//随便给的一个地址,不要轻易访问这个内存,多半出错
    10     printf("0x%x
    ", p1);
    11     p2 = &p1;//二级指针需要一级指针的地址初始化
    12             //当然,其实任意地址都可以,只是会有警告,比如下面:
    13    /*
    14     int a = 10;
    15     p2 = &a;//编译器提示:int **”与“int *”的间接级别不同
    16             //这样还是可以修改,因为本质上来说,不管你几级指针,都只是需要地址去初始化它
    17             //但是,我们应该遵循类型完全兼容的原则
    18     */
    19 
    20     *p2 = 123;
    21     printf("%d
    ", p1);//这个时候,通过二级指针修改了一级指针的值
    22     return 0;
    23 }

    再来一个体现二级指针用法的例子:

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<stdio.h>  
     3 //还是可以更改a的值,因为mp和p都指向a的地址,但要是我现在设计需求要改变p的值呢?
     4 void two_pointer(int *mp)
     5 {
     6     *mp = 30;
     7 }
     8 //要改变p的值,当然和普通变量a一样,可以直接修改,也可以间接修改
     9 //和普通变量a有需要间接修改的需求一样,指针变量p也有这样的需求
    10 //此时,二级指针就来了
    11 void two_pointer2(int **mmp)
    12 {
    13     //mmp是二级指针,不管它是多少级,始终记住,加一个(*)就像多一扇门
    14     //一级指针p修改普通变量a,我们通过*p=想要修改的数  这样的方式,同理
    15     //二级指针修改一级指针,也应该是通过*mmp=想要修改的一级指针   这样的方式
        //二级指针修改一级指针指向地址的内容时,需要两个(*),因为你需要开两次门啊!
    16 *mmp = (int *)0x100;//把一级指针p的值修改为100 17 //加强制类型转换是因为100是个立即数,而*mmp希望接受的是一个 18 //int *的地址,当然,不强转成这样只是警告,而且还是可以达到效果 19 //这个在后面写链表的程序中非常有用 20 } 21 int main() 22 { 23 int a=10; 24 printf("a=%d &a=%p ", a,&a); 25 26 int *p=&a; 27 *p = 20; 28 printf("a=%d &p=%p ", a, &p); 29 30 two_pointer(p); 31 printf("a=%d p=%p ", a,p); 32 33 two_pointer2(&p); 34 printf("p=%p ", p);//此时,p已经被修改 35 return 0; 36 }

    请君多思量,指针不过如此。

  • 相关阅读:
    The Mac Application Environment 不及格的程序员
    Xcode Plugin: Change Code In Running App Without Restart 不及格的程序员
    The property delegate of CALayer cause Crash. 不及格的程序员
    nil localizedTitle in SKProduct 不及格的程序员
    InApp Purchase 不及格的程序员
    Safari Web Content Guide 不及格的程序员
    在Mac OS X Lion 安装 XCode 3.2 不及格的程序员
    illustrate ARC with graphs 不及格的程序员
    Viewing iPhoneOptimized PNGs 不及格的程序员
    What is the dSYM? 不及格的程序员
  • 原文地址:https://www.cnblogs.com/yangguang-it/p/6618211.html
Copyright © 2011-2022 走看看