zoukankan      html  css  js  c++  java
  • 指针-2

    1. 指针的重要性:

    •   表示一些复杂的数据结构(学数据结构必须学指针)
    •   快速的传递数据
    •   使函数返回一个以上的值
    •   能后方便的处理字符串
    •   是理解面向对象语言中的基础(java)

    总结:指针是c语言的灵魂

    2. 指针的定义

     (1)地址

        内存单元的编号

        从零开始的非负整数

        范围:4G(0-4G-1)

    控制线:控制数据传输的方向

    数据线:进行数据传输

    地址线:用来确定对内存条的哪个单元进行控制(有32个地址总线,一个地址线能控制2个内存单元,32个地址线能控制2^32个内存单元)

      (2)指针

    •       指针就是地址,地址就是指针
    •       指针变量就是存放单元编号的变量,或者说指针变量就是存放地址的变量
    •       指针和指针变量时两个不同的概念
    •            注意:通常我叙述时会把指针变量简称为指针,实际上他们是不同的概念
    •       指针的本质就是一个操作受限的非负整数(指针只能相减)      

            (3)指针的分类

          1. 基本类型指针 (特别重要)  

        int * p;//p是变量的名字,(int *)表示p变量存放的是int类型变量的地址
                //int * p;不表示定义了一个名字叫做*p的变量
                //           所谓int * 类型实际就是存放int变量地址的类型
        int i = 3;
        p = &i; //  p保存了i的地址,因此p指向i
        *p= i ;  //*p就是i
    
    指针常见错误
    
    常见错误一:
    
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    
        int * p; //p是局部变量,若不初始化,则为垃圾值
        int i = 5;
        *p = i;//错误,p应该先指向一个地址,p变量里面是一个垃圾值,不知道*p里面的内容,但是把i=5修改了一个不属于你的单元
    //p = &i;*p = i;//正确
    printf("%d ", *p); return 0; } 常见错误二: #include <stdio.h> #include <stdlib.h> int main() { int i = 5; int * p; int * q; p = &i; //*q = p; //错误,int 不能向int * 转换 //*q = *p; //error,因为q没有赋值,q是一个垃圾值,*q是一个不属于你能控制的单元 p = q; //q是垃圾值,q赋给p,p也变成垃圾值 printf("%d ",*q); /* q的空间是属于本程序的,所以本程序可以读写q的内容 但是如果q内部是垃圾值,则本程序不能读写*q的内容 因为*q所代表的内存单元的控制权限并没有分配给本程序 所以本程序运行到14行就会立即出错 */ return 0; }
    互换两个数字
    
    #include <stdio.h>
    #include <stdlib.h>
    
    void exchange_1(int ,int );
    void exchange_2(int * ,int *);
    void exchange_3(int * ,int *);
    
    int main()
    {
      int a = 3;
      int b = 5;
      exchange_3(&a,&b); //exchange_2(*p,*q); 是错误的,exchange_2(a,b);是错误的
      printf("a = %d, b = %d
    ",a,b);
    }
    
     //不能完成互换功能
    void exchange(int a, int b)
    {
        int t;
        t = a;
        a = b;
        b = t;
        return ;
    }
    
    // 不能完成互换功能
     void exchange_2(int * p,int * q)// 形参名字是p,q接收实参数据的是a和b的地址
     {
         int * t; //如果要互换p和q的值,则t必须是 int *类型,不能是int类型,否则会出错。
    
         t = p;  //此程序不能说是互换a和b的地址,因为静态变量的地址是死的,一旦分配则我无法更改,所以不能说互换了a和b的地址
         p = q;  //此程序只是互换了p,q的地址。a,b地址不变,仍然a=3,b = 5;
         q = t;
     } //讲解链接:https://www.bilibili.com/video/av8074534/?p=127
     
     //可以完成互换的功能
    void exchange_3(int * p,int * q)
     {
         int t; //如果要互换*p和*q的值,则t必须定义成int,不能定义int *,否则会出错
    
         t = *p; //p是 int *, *p 是int(*p代表以p地址为整型的变量)
         *p = *q;
         *q = t;
     }

     exchange_2(int * p, int * q)不能互换两值的讲解

     

    附注:

      *的含义

        1. 乘法

        2. 定义指针变量      

          int * p; //定义了一个名叫p的变量, int  *表示p只能存放int变量的地址

        3. 指针运算符

            该运算符放在已经定义好的指针变量的前面

            如果p是已经定义好的指针变量,则 *p表示  以p的内容为地址的变量

            例:int * p; //定义一个p的指针变量

              *p = 5; 

      如何通过被调函数修改主调函数普通变量的值

        1.  实参必须为该普通变量的地址

        2.  形参必须为指针变量

        3. 在被调函数中通过

             * 形参名 = .......

        的方式就可以修改主调函数相关变量的值

    #include <stdio.h>
    #include <stdlib.h>
    
    void exchange_3(int * ,int * );
    
    void exchange_3(int * p,int * q)
    {
        int t; 
        t = *p;
        *p = *q;
        *q = t;
        return ;
    }
    
    int main()
    {
        int a = 3;
        int b = 5;
        exchange_3(&a,&b);
        printf("a = %d, b = %d",a,b);
        return 0;
    }

       2.   指针和数组

          指针和一维数组

            一维数组名

                一维数组名是个指针常量,它存放的是一维数组第一个元素的地址

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int a[5]; //a是数组名, 5是数组元素的个数, 元素就是变量,  a[0] -- a[4]
    //  int a[3][4];  //3行4列,a[0][0]是第一个元素, a[i][j]是第i+1行第j+1列
        int b[5];
    
        //a = b; //error a是常量
        printf("%#X
    ",&a[0]);
        printf("%#X
    ",a);
        return 0;
    }
    /* 
    输出结果:
    0X60FEFC
    0X60FEFC
    
    Process returned 0 (0x0)   execution time : 0.639 s
    Press any key to continue.
            总结:
             一维数组名
               一维数组名是个指针常量
                         它存放的是一维数组第一个元素的地址
    */
    View Code

            下标和指针的关系

              如果p是个指针变量,则p[i] 永远等价于 *(p+i)

            确定一个一维数组需要几个参数【如果一个函数要处理一个一维数组,则需要接收该数组的哪些信息】

              需要两个参数:

                  数组第一个元素的地址

                  数组的长度

    #include <stdio.h>
    #include <stdlib.h>
    
    //f可以输出任何一个一维数组的内容
    void f(int *pArr, int len)
    {
        int i;
        for(i=0;i<len;i++)
        {
            printf("%d ", *(pArr+i)); //*(pArr+i) 等价于 pArr[i] 也等价于 b[i]  也等价于 *(b+i)
        }
        printf("
    ");
    
    }
    int main()
    {
     int a[5] = {1,2,3,4,5};
     int b[6] = {-1,-2,-3,4,5,-6};
     int c[100] = {1, 99, 22, 33};
     f(a,5); //a是int *类型
     f(b,6);
     f(c,100);
     return 0;
    }
    View Code

     

    上面程序输出结果:4 88     

      指针变量的运算

        指针变量不能相加,相乘,相除,只能相减

        如果两个指针变量指向的是同一块连续空间中的不同的存储单元,则这两个指针变量才可以相减

            

    int main()
    {
        int i = 5;
        int j = 10;
        int * p = &i;
        int * q = &j;
        int a[5];
        p = &a[1];
        q = &a[4];
        printf("p和q所指向的单元相隔%d个单元",q-p);
        //p-q没有实际意义
        return 0;
    }
    View Code

       一个指针变量到底占几个字节【非重点】

          预备知识:

            sizeof(数据类型) 

            功能:返回值就是该数据类型所占的字节数  例子:sizeof(int) = 4  sizeof(char)= 1

            sizeof(变量名)

            功能:返回值是该变量所占的字节数

          假设p指向char类型变量(1个字节)

          假设q指向int类型变量(4个字节)

          假设r指向double类型变量(8个字节)

          p q r 本身所占的字节数是否一样  答案:一样的

        总结:一个指针变量,无论它指向的变量时几个字节,该指针变量本身只占四个字节; 一个变量的地址是用该变量首字节的地址表示

     

    总结:1. x用第一个字节表示 

       2.  r中存放第一个字节的地址

         3.  根据r前面的数据类型可以确定r变量的类型(即所占字节数是多少)

       4.  r只存放第一个字节的地址但sizeof(*r)=4。说明第一个字节的地址(类似房间的编号,房间有大有小,当特别大的时候一个字节盛不下,就用四个字节老保存)要用四个字节保存 

        指针和二维数组(难,可以先不用看)

  • 相关阅读:
    c#,winform,progressbar+labe,联动显示进度 Virus
    答某刘
    Expert .NET 2.0 IL Assembler·一校日记 (2)
    IL 二校汇总
    历史的思考(1)
    酝酿中,写一本《你不知道的IL》
    Expert .NET 2.0 IL Assembler·一校日记
    一校 疑难汇总
    强签名
    [转] 《解剖PetShop》系列之三
  • 原文地址:https://www.cnblogs.com/spore/p/11030164.html
Copyright © 2011-2022 走看看