zoukankan      html  css  js  c++  java
  • 2019年2月12日训练日记(指针及其应用)

    今天总结一下指针的知识点与指针的使用

    指针及其应用

    第一节 指针变量

    指针变量的定义、赋值:
    指针定义的一般形式:
    类型说明符*变量名
    其中,*表示这是一个指针变量,变量名及为指针的变量名,类型说明符表示该指针变量所指向的变量的数据类型。
    例:int *p=NULL;
    定义了一个指针变量p,p指向一个内存空间,里面存放的是一个内存地址。现在赋值为NULL(其实就是0,特殊的空地址)
    给指针变量p赋值:
    一、指针变量初始化的方法:
    int a;int *p=&a;
    二、赋值语句的方法:
    int a;int *p;p=&a;
    三、int *p=new(int);代表申请给p一个空间,*p内容不能确定。

    不允许把一个数赋值给指针变量,故如下的赋值语句是错误的:int p=1000;(此句代表指针p指向内存地址为1000的数值,谁也无法确定将会是什么,随意修改或赋值可能会产生错误,甚至破坏程序或系统内存的值等,引发不可预测的错误)被赋值的指针变量前不能再加””说明符,故如下的赋值语句也是错误的:p=&a;。赋值之后,p就代表指针p指向的整型变量,而p中存放的就是a占用单元的起止地址。另外要注意的是:必须明确p指向的数据类型,类型不一样的不仅空间大小不相同,储存格式也不同。有的时候可能会使用无类型指针,对指针进行赋值后,最后在运算、输出等操作时必须明确p指向的数据类型,例如输出时:cout<<(int)p;
    多重指针:指针是指向其他类型的,其实指针也是一种类型。C++允许使用递归地指针指向指针的指针——多重指针。
    例:双重指针

    int a=10;
    int *p;
    int * *pp;
    p=&a;        //将p指向a
    pp=&p;      //将pp指向p
    printf(“%d=%d=%d
    ”,a,*p,* *pp);
    

    输出:10=10=10
    多重指针除了可以多次“间接”访问数据,OI上主要应用动态的多维数组。

    第二节 指针与数组

    指针与数组的关系:
    指向数组的指针变量称为数组指针变量。一个数组是一个连续的内存单元,数组名就是该单元的首地址。一个指针可以指向一个数组,也可以指向其中一个数组元素。假如指针要指向数组的第i号元素,可以把数组的第i元素的首地址赋予它,或把数组名加i赋予它。
    指向数组的指针:
    数组指针变量说明的一般形式:
    类型说明符 指针变量名
    其中类型说明符表示所指数组的类型。
    当访问数组元素时,有以下两种形式:
    一、下标法:即用p[i]形式访问a的数组元素
    二、指针法:即采用
    (p+i)形式,用间接访问的方法来访问数组元素。
    指针也可以看作数组名:
    指针可以动态申请空间,如果一次申请多个变量空间,系统给的地址是连续的,就可以当成数组使用,这就是动态数组的一种。
    例:
    int *a;
    a=new int [n+1]; //向操作系统申请了连续的n+1个int型的空间
    这样就可以利用已知的数据n规划内存空间(动态规划,n变内存空间变)
    动态数组的优点:对于大数据可能超内存的情况是比较纠结的事,用小数组只得部分分,大数组可能爆空间(得0分)。使用“动态数组”,可以确保小数据没问题的前提下,尽量满足大数据的需求。
    另外需要注意的指针运算问题:
    例如指针p++的意思并不是和广义上的加1,不是p的值(地址)加1,而是根据类型int增加sizeof(int),即刚好跳过一个整数的空间,达到下一个整数,由此类推,p+i即p根据类型跳过sizeof(类型)个空间。

    第三节 指针与字符串

    在C++中我们访问字符串可以通过数组存放并输出的形式,还可以用字符指针指向一个字符串。
    例:
    char *str=“I love China!”;
    printf(“%s ”,str);
    等价于:
    char *str;
    str=“I love China!”;
    printf(“%s ”,str);

    这里并不是将字符串赋值给指针,指针的作用只是存放地址,不能存放字符串,这里只是将字符串第一个元素的地址(即存放字符串的字符数组的首地址)赋给str。

    第四节 指针与函数

    指针可以作为函数的参数。在我们把数字作为参数传到函数时,实际上就是利用了传递指针(即传递数组的首地址)的方法。通过首地址,我们能访问数组中任何一个元素。
    一个函数可以返回整数型、字符型、实型等,也可以返回指针联系的数据(即地址)。
    返回指针值的函数一般定义形式为:类型名 函数名(参数列表);例如:int a(int a,int b)其中a是函数名,调用它后得到一个指向整型数据的指针(地址)。x和y是函数a的形参,为整型。
    注意:在
    a的两侧没有括号,在a的两侧分别为
    运算符和()运算符,由于()的优先级别高于*,因此a先于()结合。在函数前面有一个*,表示此函数是返回指针类型的函数。最前的int表示返回的指针指向整型变量。
    另外,函数的入口地址也同样可以使用指针访问。但是,有些函数在编写时可能对要用的辅助函数尚未确定,在执行时才能根据情况为其传递辅助函数的地址。比如sort的调用:“sort(a,a+n,cmp);”其中的比较函数cmp是我们根据需要转给sort的(也可能是cmp1,cmp2等),其实就是传递了函数指针。
    例:

    #include<iostream>
    using namespace std;
    int t(int a)
    {
        return a;
    }
    int main()
    {
        cout<<t<<endl;        //显示函数地址
        int (*p)(int a);     //定义函数指针变量p
        p=t;                //将函数t的地址赋给函数指针p
        cout<<p(5)<<','<<(*p)(10)<<endl;
    //输出p(5)是C++的写法,(*p)(10)是兼容C,这里使用p来调用函数的两种方法
    return 0;
    }
    

    输出:
    1
    5,10

    函数的基本操作
    一、声明函数指针。
    声明要指定函数的返回值类型以及函数的参数列表,和函数原型差不多。例如,函数的原型是:int test(int );相应的函数声明就是:int (*fp)(int );要注意的是,不能写成:int *fp(int );这样计算机编译程序会处理成声明一个fp(int )的函数,返回类型是int *。
    二、获取函数的地址。
    获取函数的地址只要使用函数名即可,例如:fp=test;这表明函数名和数组名一样,可以看作是指针。
    三、使用函数指针来调用函数。
    类似于普通变量指针,可以用(*fp)来间接调用函数指向的函数。但C++也允许像使用函数名一样使用fp(存在争议)。
    另外函数指针还有typedef定义,定义格式如下:
    typedef int (*LP)(int,int); //定义了一个函数指针变量类型LP
    LP p=sum; //定义了一个LP类型的函数指针p,并赋值为sum
    另外可以通过typedef定义函数指针来定义一个函数指针变量类型的函数指针数组,也可以同时为其初始化,这样可以应用于菜单功能区函数的调用,减少switch/case或if语句处理的复杂、冗长,并且这样有利于代码的维护,更加方便灵活。

    第五节 结构体指针

    结构体指针的定义与使用:
    结构体指针变量定义的一般形式:
    结构体名 *结构体指针变量名
    引用结构体指针变量指向的结构体变量的成员的方法如下:
    一、指针名->成员名
    二、(*指针名).成员名
    例:(*p).score与p->score是等价的。
    自引用结构:
    在一个结构体内部包含一个类型为该结构体本身的成员是不合法的,因为成员p是一个完整的结构,它将还包含自己的成员p,这样就会导致无限重复下去。例:

    struct stu
    {
       	char name[20];
     	 int age,score;
    	 stu p;
     };
    

    是非法的。
    但是:

    struct stu
    {
     char name[20];
       int age,score;
    	  stu *p;
    };
    

    是合法的。
    区别就是现在的p是一个指针而不是结构体,因为编译器在结构体的长度确定之前就已经确定了指针的长度,所以这种类型的自引用是合法的。
    当一个结构体中有一个或是多个成员是指针,它们所指向的类型就是本结构体类型时,通常这种结构称为“引用自身的结构体”,即“自引用结构”。这种自引用结构是实现其它一些结构的基础。
    自引用结构在动态数据结构中有重要作用,甚至可以说,自引用结构是C/C++语言实现动态数据结构的基石。包括动态的链表、堆、栈、树,无不是自引用结构的具体实现。

  • 相关阅读:
    Visual Studio 2010使用Visual Assist X的方法
    SQL Server 2000 评估版 升级到 SQL Server 2000 零售版
    双网卡多网络单主机同时访问
    开发即过程!立此纪念一个IT新名词的诞生
    delphi dxBarManager1 目录遍历 转为RzCheckTree2树
    5320 软件集合
    delphi tree 从一个表复制到另一个表
    DELPHI 排课系统课表
    长沙金思维 出现在GOOGLE的 金思维 相关搜索里啦!!
    如何在DBGrid的每一行前加一个单选框?
  • 原文地址:https://www.cnblogs.com/study-hard-forever/p/12130057.html
Copyright © 2011-2022 走看看