• 指针的用法


                 大家都应该知道, 指针是个什么玩意儿, 它就是用来存另一个变量的地址的。这玩意儿在程序中容易引起不易察觉的错误, 而且会给调试带来莫大的困难。 尽管如此,它现在依然存在着, 这就从另一方面说明了, 它的功能爆表。 在实现链式存储, 图, 树, 森林时, 大都要用指针。 不仅如此, 在访问多维数组,函数参数传递时, 也多用指针。下面给出指针的一些常用的用法代码。

        

    /*指针的声明及一般用法*/
    /*________________________________________________________________*/ 
    //声明:
    int a;
    int *p=&a;
    
    int a;
    int *p;
    p=&a;
    
    #include<stdio.h>
    int main()
    {
        int a, b;
        int *ipointer1, *ipointer2;
        scanf("%d%d", &a, &b);
        ipointer1 = &a;
        ipointer2 = &b;
        printf("The number is:%d %d
    ", *ipointer1, *pointer2);
    } 
    
    #include<stdio.h>
    int main()
    {
        int *p, q;
        p=&q;
        scanf("%d", p);//另类写法。 
        printf("%d
    ", q);
        return 0;
    }
    
    //&*和*&的区别, &和*的优先级相同。运算顺序从左向右。
    #include<stdio.h>
    int main()
    {
        int i;
        int *p;
        scanf("%d", &i);
        p=&i;
        printf("%d
    ", *&i);
        printf("%d
    ", i);
        printf("%d
    ", *p);
        printf("%d
    ", &*p);
        return 0;
    } 
    
    //指针的自增自减。 
    #include<stdio.h>
    int main()
    {
        int i;
        int *p;//将变量i的地址赋给指针变量。 
        scanf("%d", &i);
        p=&i;
        printf("%d
    ", p);
        p++;//指针变量加1, 这里的加 1 并不代表一个字节与*p的类型有关。 
        printf("%d
    ", p);
        return 0;
    } 
    
    //一维数组与指针
    int *p, a[10];
    p=&a;
    
    int *p, a[10];
    p=&a[0];
    
    #include<stdio.h>
    int main()
    {
        int *p, *q, a[5], b[5], i;
        p=&a[0];
        q=b;//数组名就代表地址。 
        for(i=0; i<5; i++)
        scanf("%d", &a[i]);
        for(i=0; i<5; i++)
        scanf("%d", &b[i]);
        for(i=0; i<5; i++)
        printf("%5d", *(p+i));
        printf("
    ");
        for(i=0; i<5; i++)
        printf("%5d", *(q+i));
        return 0;
    }
    #include<stdio.h>
    int main()
    {
        int *p, *q, a[5], b[5], i;
        p=&a[0];
        q=b;
        for(i=0; i<5; i++)
        scanf("%d", p++);
        for(i=0; i<5; i++)
        scanf("%d", q++);
        p=a;//使指针变量p,q 重新指向数组起始位置。 
        q=b;
        for(i=0;i<5; i++)
        printf("%5d", *p++);
        printf("
    ");
        printf("%5d", *q++);
        return 0;
    } 
    //二维数组与指针。 
    #include<stdio.h>
    int main()
    {
        int a[3][5], i, j;
        for(i=0; i<3; i++)
        {
            for(j=0; j<5; j++)
            scanf("%d", a[i]+j);
        }
        for(i=0; i<3; i++)
        {
            for(j=0; j<5; j++)
            printf("%5d", *(a[i]+j));
            printf("
    ");
        }
        return 0;
    }
    
    //
    #include<stdio.h>
    int main()
    {
        int a[3][5], i, j, *p;
        p=a[0];
        for(i=0; i<3; i++)
        {
            for(j=0; j<5; j++)
            scanf("%d", p++);
        }
    }
    p=a[0];
    for(i=0; i<3; i++)
    {
        for(j=0; j<5; j++)
        printf("%5d", *p++);
        printf("
    ");
    }
    
    #include<stdio.h>
    int main()
    {
        int a[3][5], i, j, (*p)[5];
        p=&a[0];
        for(i=0; i<3; i++)        //控制二维数组的行数。 
        for(j=0; j<5; j++)       //控制二维数组的列数。 
        scanf("%d", (*(p+i))+j); //为二维数组中的元素赋值。 
        p=&a[1];                //*p为第一个元素的地址。 
        for(j=0; j<5; j++)
        printf("%5d", *((*p)+j));//输出二维数组中的元素。 
        printf("
    ");
        return 0;
    }
    #include<stdio.h>
    int main()
    {
        int a[3][5], i, j;
        for(i=0; i<3; i++)
        for(j=0; j<5; j++)
        scanf("%d", *(a+i)+j);
        for(j=0; j<5; j++)
        printf("%5d", *(*(a)+j));
        printf("
    ");
        return 0;
    }
    
    //
    #include<stdio.h>
    int main()
    {
        char str1[]="you are beautiful", str2[30], *p1, *p2;
        p1 = str1;
        p2 = str2;
        while(*p1!='')
        {
            *p2 = *p1;
            p1++;
            p2++;
        }
        *p2='';
        printf("Now the string2 is:
    ");
        puts(str2);
        return 0;
    }
    View Code

     上面的代码只是给出了,指针的一般用法。 如果你想比较深入的理解一下指针是什么鬼, 下面的文字也许对你有些帮助。 

    首先给出一个警告: 一定要在对指针应用解除引用运算符(*)之前, 将指针初始化为一个确定的, 适当的地址。 -----这是关于使用指针的金科玉律。

    误用指针的原因:

    在C++中创建指针时, 计算机只分配了用来存放地址的内存, 而没有分配用来存储指针所指向的数据的内存。 为数据提供空间是一个独立的步骤, 而忽略这一步骤, 就可能带啦灾难性的bug。

    //错误代码, 请勿模仿。 
    int* p;
    *p = 5; 

    上面的 p 的确是一个指针, 但是并不知道它指向哪里去了? 上述代码没有将地址赋给 p 。 那么 5 放到了哪里去了呢?----------》 鬼知道 。  由于 p 指向的地方不知道在哪里。 (没准是你的程序中关键代码的地址) 。 如果是这样, 就可能会导致一些最隐匿, 最难以跟踪的bug。

    空指针: C++确保空指针不会指向有效的数据, 因此它常被表示运算符或函数失败(如果成功, 它们将返回一个有用的指针)。

    空指针的声明方法:

    int *p1 = nullptr;

    int *p2 = 0;

    int *p3=NULL

    //上述三种声明方式等价。

    事实上, 数组名和指针是差不多的,编译器在编译数组时, 会把数组编译成指针的形式。

    a[i] 会被编译成 *(a+i)
    //你知道的, 数组的首地址相当于指针,
    //而 i 的值是编译器会根据数组的类型
    //而定的。 
    而一个指针变量, 如果让它指向一个数组首地址
    也可以用数组的形式来访问数组元素。
    int a[3]={1, 2, 10}
    int*p = a;//*p = &a[0]
    cout<<p[0]<<endl;
    cout<<p[1]<<endl;

    当然, 数组名和指针还是有区别的。  区别一: 可以修改指针的值, 因为指针是指针变量。 但是数组名是常量, 不能更改!。 区别二: 对数组应用sizeof运算符得到的是数组的长度, 而对指针应用sizeof的得到的是指针的长度。

    数组的地址:

    其实对数组取地址时, 数组名也不会完全被解释为数组的地址。 数组名被解释为其第一个元素的地址, 而对数组名应用地址运算符时, 得到的是整个数组的地址:

    int a[10];
    cout<<a<<endl;//displays &a[0]
    cout<<&a<<endl;//displays address of whole array
    //从数值上说, 这两个地址相同, 但是从概念上说缺有区别
    //&a[0] 是 一个4字节的内存地址(即:告诉计算机要4个字节)。
    //&a 是一个40字节的内存地址(即:告诉计算机要40个字节的空间)
    //数组地址的这个特点为多维数组实现提供了方便。 

     void*指针:

       void*是一种特殊的指针类型,可以存放任意对象的地址(如: int型, double型, char型, 函数形, 结构体型, 等)。一个void*指针存放着一个地址, 这一点和其他指针类型类似。 不同的是我们对该地址中到底是什么类型的对象并不了解。因此不能直接操作void*指针所指的对象。 但是可以比较它和别的指针的大小, 作为函数的输入输出, 或者赋值给另外一个void*。

    指向指针的引用:

    int i=42;                        

    int *p;                 // p是一个int型的指针          

    int *&r = p;         //r是一个对指针p的引用.

    r=&i;                  //r引用了一个指针,因此给r赋值&i就是令p指向i。

    *r = 0;               //解引用r得到 i,也就是p指向的对象, 并将i的值改为0

     

    下面是一个关于指针的程序的简单分析:

    #include<cstdio>
    #include<iostream>
    using namespace std;
    
    int fun(int *data)
    {
        return (*data)++;
    } 
    
    int main()
    {
        int data = 55;
        cout << fun(&data) << endl;
        cout << data <<endl;
        data = fun(&data);
        cout << data <<endl;
        return 0;
    }

    本程序输出的是 55 56 56

    是不是感到很神奇呢? 分析此程序可以知道 形参是指针类型的, 所以它是可以改变main()里的data的值的。 第一次调用fun()时, data=55, 然后返回 *data 给cout输出流(此时值为55) 相当于赋值给另一个变量了(这才是输出的值), 然后 *data+1  也即是: main()中的data+1, 此时data = 56. 所以第二次输出为56. 然后 是同样的 data = fun(&data) 这是关键的一句。 fun()函数返回 56, 然后 data+1 = 57  然后是 data = fun()的值, 由于fun()返回的值是56, 所以57被覆盖啦。因此第三次data输出 56.         建议上机调试此程序,以便更深入的理解。  提示: 不要在DEV C++里调试, 这个编译器的调试软件版本较老,调试此程序时可能有误!建议在 VS2010或更高版本上调试。

     

    下面是关于一个指针的引用的示例:

    #include<iostream>
    int main()
    {
        using namespace std;
        int rats = 101;
        int *pt = &rats;
        int &rodents = *pt;  // 在声明的时候, 将rodents初始化为 *pt 
        int bunnies = 50;    // 使得rodents指向了 rats。而后不再随 
        pt = &bunnies;        //*pt的改变而改变。 
        cout << "rats = "<< rats << endl;
        cout << "*pt = " << *pt << endl;
        cout << "rodents = " << rodents << endl;
        cout << "bunnies = " << bunnies << endl;
        cout << "rats's address = " << &rats << endl;
        cout << "rodents's address = " << &rodents << endl;
        cout << "*pt's address = " << pt << endl;
        return 0;
    } 

    以上现象出现的原因是, 引用必须初始化,而且一旦初始化,就不再改变!

    常见的因指针误用导致的存储器错误

     

  • 相关阅读:
    浅析uitableview
    ios9和xcode7的适配问题
    uiviewContentMode的介绍 转载
    关于常见的加密算法浅析
    程序中发起电话呼叫
    单例实现方式以及类方法和实例方法
    windows下的git的安装教程
    上传github项目
    android 使用SurfaceView绘制一个简单动画控件
    android 自定义控件属性获取bitmap和drawable的绘制
  • 原文地址:https://www.cnblogs.com/acm1314/p/4509141.html
Copyright © 2020-2023  润新知