zoukankan      html  css  js  c++  java
  • 关于指针

    一个数据对象的内存地址称为该数据对象的指针

    指针和引用的区别:
    (1)非空区别。在任何情况下都不能使用指向空值的引用。一个引用必须总是指向某些对象。
    (2)合法性区别。在使用引用之前不需要测试它的合法性。相反,指针则应该总是被测试,防止其为空。
    (3)可修改区别。指针与引用的另一个重要的不同是指针可以被重新赋值以指向另一个不同的对象。但是
    引用则总是指向在初始化时被指定的对象,以后不能改变,但是指定的对象其内容可以改变。
    (4)应用区别。总的来说,在以下情况下应该使用指针:一是你考虑到存在不指向任何对象的可能(这种
    情况下,你能够设置指针为空),二是你需要能够在不同的时刻指向不同的对象(在这种情况下,你能改
    变指针的指向)。如果总是指向一个对象并且一旦指向一个对象后就不会改变指向,那么你应该使用引用。

    例1:
    int iv;                  //正确,声明一个整型变量
    int &reiv;            //错误,声明一个引用,但引用不能为空,必须同时初始化这个变量
    int &reiv2=iv;     //正确,声明一个引用rev2,同时初始化了,也就是reiv2是iv的别名
    int *pi;               //正确,声明一个整型指针,但是并没有定义这个指针所指向的地址
    *pi=5;                //错误,整数指针pi并没有指向实际的地址。在这种情况下就给它赋值是错误的,因为赋的值不知道该放到哪里去,从而造成错误。
    const double di;               //错误,const常量赋值时,必须同时初始化。
    const double maxWage=10.0;     //正确
    const double *pc=&maxWage;     //正确,const常量指针赋值并同时初始化。



    例2:程序员面试宝典中的题
    const char *strA()
    {
       char *str = "helloword";

       return str;
    }

    const char *strA()
    {
      char str[] = "helloword";

      return str;
    }
    为什么说   char *str = "helloword";是全局数组呢?
    而char str[] = "helloword";是局部数组?

    答:char* str = "helloword"时,函数的局部变量只占用4B,因为只声明了一个指针,
    它指向了全局数据区里的一串字符,也就是说字符串的内容还是放在全局数据区里的.
    比如"helloword"这个字符串被编译器安排到0x1000到0x1009这段长度为10的内存里,
    这条语句运行的时候就相当于char* str = 0x1000,而char str[] = "helloword"时,
    函数的局部变量占用了10B,因为它相当于:char str[10] ={104,101,...100,0},也就
    是说字符串的内容是直接放在函数用的内存里的.

    局部数组是局部变量,它所对应的是内存中的栈。全局数组是全局变量,它所对应的
    是内存的全局区域。
    全局区域的值是不能进行修改的

     

    例3:写出1函数指针、2函数返回指针、3const指针、4指向const的指针(指针指向的内容
    是不能被修改的)、5指向const的const指针

    1.void (*f)()

    2.void *f()

    3.int* const p=一个地址; (因为指针本身的值是不能被修改的所以它必须被初始化)

    4.const int* p(推荐)或者int const* p

    5.const int* const p

    例4:下列程序的输出结果是什么?

    #include<iostream>

    using namespace std;


    class A
    {
    public:
        int _a;
        A()
        {
            _a=1;
        }
        void print()
        {
            printf("%d",_a);
        }
    };


    class B:public A
    {
    public:
        int _a;
        B()
        {
            _a=2;
        }
    };

    int main()
    {
        B b;
        b.print();
        printf("%d ",b._a);
        return 0;
    }
    解析:在执行语句B b;时,首先构造B类需先调用A类的构造函数,再调用B类的构造函数
    在执行b.print();时,直接调用A类的print()函数,此时this->_a=1
    所以答案为:12
     
     
    例5:
    #include<iostream>

    using namespace std;


    struct S
    {
        int i;
        int* p;
    };

    void main()
    {
        S s;                   
        int *p=&s.i;          //1
        p[0]=1;                //2
        p[1]=5;               //3
        s.p=p;                //4
        s.p[0]=2;           //5
        s.p[1]=7;           //6
    }
    开始:
    执行完1时:
     
    执行完2时:
    执行完3时:
    执行完4时:
    执行完5时:
    执行完6时:
    现在,若把最后两行调换位置,结果会咋样?即:
     s.p[1]=7;           //5
     s.p[0]=2;           //6
    答案是程序会在s.p[1]=7; 处崩溃。
    原因是:s.p[1]=7相当于s.p=7;把0x00000007存入s.p的空间。
    s.p[0]=2;并不是给s.i赋值,而是相当于*((int*)0x00000007)=2;
    也就是要访问0x00000007空间-----对于一个未作声明的地址直接进行访问,所以访问会出错。
  • 相关阅读:
    java基础
    php中的$_REQUEST超全局变量
    update 数据表 set 字段1=字段1+id的sql语句
    青蛙跳台阶的相关问题
    Java语言实现石头剪刀布游戏
    Java语言实现palindrome(回文)
    Java语言实现奇怪的比赛
    Java语言实现随意组合
    Java编辑器IDEA的下载与安装
    Vscode下载与汉化
  • 原文地址:https://www.cnblogs.com/fuxianfeng1988/p/3248455.html
Copyright © 2011-2022 走看看