zoukankan      html  css  js  c++  java
  • C++指针

    引言:运行下列代码。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    int main()
    {
      int t=7;
      int *a;//这显然是定义了一个指针,int* a等价于int *a
      a=new int;
      a=&t;
      printf("%d ",*a);
       printf("%p",a);
       delete a;
      return 0
    }

        运行结果,在我的电脑上是7 0023FF18。放着问题不说,先讲结论。

        我们要研究指针,需要知道四个内容:指针的类型,指针指向的变量的类型,指针的值,指针本身占据的内存区域(首先我们要知道指针是“指”向一个变量的变量)。

        1. 指针的类型:定义的形式在程序段中写了。我们可以把指针的名称去掉,看剩余部分。下面是几个例子。

        int *p;  int *()表示我们定义了一个指向整形的指针变量。这是一个相当单纯的指针类型,那么对于更复杂的指针类型,我们如何分析?

        int *p[3]; 首先p与“[]”结合,表明p是一个数组(“[]”的优先级比“*”高)。再与“*”结合,表明p里面的元素是指针。最后与int结合,表明p里面的指针元素是指向整形的。

        int (*p)(int); p先与“*”结合,表明p是一个指针,再与“()”结合,说明这是一个函数,且该函数有一个整形参数。再与最外面的int结合,说明该函数的返回值为整形。因此p是一个指向一个有一个整形参数且返回值为整形的函数的指针。

        2.指针指向的变量的类型:只需把指针的名称和其左边的“*”去掉,剩下的部分就是指针指向的变量的类型。

        3.指针的值:在这里我终于要填坑了。之前我们有这样一句话:a=new int; 这句话的意思是为指针a开辟内存空间。我们知道计算机存储数据都是需要空间的(这里俺也知道的不多,就不细讲了……)同理,我们程序中的变量也有自己的空间。计算机访问变量是通过访问变量所在的地址实现的。指针的“值”,也就是指针指向的变量的地址。后面我们还有一句话:delete a; 这句话的意思是释放指针a 的内存空间,也就是说这一步之后指针a就没有内容了。还有,之前输出了一个指针的地址。如果你多试几次,你会发现那个值是固定的,而且就算你关闭C++再重启也是一样,但如果你关机重启,它就会是另一个固定的值了。
        我们都知道,赋值号左右的部分必须是类型相同的量。那么这一句话:a=&t; “&”的作用就呼之欲出了,没错,“&t”的作用就是返回t的地址。你可能会问,为什么使用指针a的时候不带“*”号?那是因为“*”的作用是表明a是一个指针,当我们用的时候只要用指针的名称就行了。就好像定义常量的时候我们会写:const int a=7; 但后面用的时候我并不必带上“const”。在回想一下其余的部分。我们经常见到的使用“&”的时候是使用“scanf”时,现在我们知道了,是因为“scanf”是需要用到地址。但指针本来就是一个地址,所以,如果想读入指针,直接读就好了。Code如下:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    int main()
    {
      
    int *a=new int;   scanf("%d",a);   printf("%d",*a);   return 0; }

        4.指针自己所占的内存:指针指向某个变量在内存中的地址,它自己也肯定占一定的空间。指针本身占了多大的内存?你只要用函数sizeof(指针的类型)测一下就知道了。在32位平台里,指针本身占据了4个字节的长度。

        5.指针的算术运算

        如果你给一个指针加上或减去一个数n(咱只知道整数),那么相当于加上或减去n*(sizeof(指针指向的变量的类型))。在数组中比较常用。

    Code:

    int a[20];  
    int *p=a;//我略去了开空间的步骤,大家别忘啊!  
    ...  
    //此处略去为整型数组赋值的代码。  
    ...  
    for (i=1; i<=20; i++)  
    {  
        (*p)++;  
        p++;  
    }

    上述代码可以用来给整个数组中的元素加1。是不是有点danteng……不要在意这些细节啦。

        6.指针与数组名

        数组名其实也就是一个指针。所以我们可以这样:

    value=a[0];//也可写成:value=*a;   
    value=a[3];//也可写成:value=*(a+3);   
    value=a[4];//也可写成:value=*(a+4);

        值得注意的是数组名有双重含义,所以a++之类的操作是不行的。

        7.指针与结构类型

        我们看下面的代码:

    struct node  
    {  
      int a,b,c;  
    };  
    
    node ss={20,30,40};//声明了结构对象ss,并把ss的三个成员初始化为20,30和40。
    node *p1=&ss;//声明了一个指向结构对象ss的指针。它的类型是node*,它指向的类型是node。
    int *p2=(int*)&ss;//声明了一个指向结构对象ss的指针。但是它的类型和它指向的类型和ptr是不同的。

        我们怎么用指针p1和p2访问ss的三个成员呢?

    p1->a;
    p1->b;
    p1->c;
    *p2;//访问了ss的成员a。  
    *(p2+1);//访问了ss的成员b。  
    *(p2+2)//访问了ss的成员c。

        但其实p2的方法是不规范的。为什么呢?

        所有的C/C++编译器在排列数组的单元时,总是把各个数组单元存放在连续的存储区里,单元和单元之间没有空隙。但在存放结构对象的各个成员时,在某种编译环境下,可能会需要字对齐或双字对齐或者是别的什么对齐,需要在相邻两个成员之间加若干个“填充字节”,这就导致各个成员之间可能会有若干个字节的空隙。如果你直接访问的话,那么你就有很大的可能会访问到填充字节。









         

         

          

          


  • 相关阅读:
    省选模板_简单数学
    省选模板大杂烩
    省选_简单算法
    省选_简单图论
    省选_简单数据结构
    BZOJ4545: DQS的trie 广义后缀自动机 + LCT
    BZOJ 4229: 选择 LCT + 独创方法 + 边双
    luoguP2742 【模板】二维凸包 / [USACO5.1]圈奶牛 二维凸包
    python面向过程编程小程序 -ATM(里面用了终端打印)
    从7点到9点写的小程序(用了模块导入,python终端颜色显示,用了点局部和全局可变和不可变作用域,模块全是自定义)
  • 原文地址:https://www.cnblogs.com/Shymuel/p/4393142.html
Copyright © 2011-2022 走看看