zoukankan      html  css  js  c++  java
  • C语言之指针

    指针

    指针和指针变量的关系
      指针就是地址,地址就是指针
      地址就是内存单元的编号
      指针变量是存放地址(内存单元的编号)的变量
      指针和指针变量是两个不同的概念
      但要注意:通常我们会把指针变量简称为指针表,实际含义不一样
      指针的本质就是一个操作受限的非负整数
      重要性:
      表示一些复杂的数据结构
      快速的传递数据  减少了内存的耗用【重点】
      使函数返回一个以上的值【重点】
      能直接访问硬件
      能够方便的处理字符串
      是理解面向对象语言中引用的基础
      定义:
         地址:
       内存单元的编号
              从0开始的非负整数
              范围:4G  【0---4G-1】
      分类:
        1.基本类型指针【重点】
      附注:
           *的含义
              1.乘法
              2.定义指针变量
                  int  *p;//定义一个名字叫p的变量,int *表示p只能存放       int变量地址
              3.指针运算符
                  该运算符放在已经定义好的指针变量的前面
                  如果p是一个已经定义好的指针变量
                  则*p表示以p的内容为地址的变量
      如何通过被调函数修改主调函数普通变量的值
          1.实参必须为该普通变量的地址
          2.形参必须为指针变量
          3.在被调函数中通过
                  *形参名  =  ·····
             的方式就可以修改主调函数相关变量的值
        2.指针和数组
         指针和一维数组
              一维数组名:
                  一维数组名是个指针常量
                  它存放的是数组第一个元素的地址
              下标和指针的关系
                  如果p是个指针变量,则
                      p[i]永远等价于  *(p+i)
      确定一个一维数组需要几个参数【如果一个函数要接受一个一维数组,需要哪些条件】数组第一个元素的地址和数组长度   
    # include <stdio.h>
    
    //f函数可以输出任何一个一维数组的内容 
    void f(int * pArr,int len)
    {
        int i;
        for(i = 0;i < len;++i)
            printf("%d",*(pArr + i));   /*(pArr + i)等价于 pArr[i]  也等价于  数组[i]
        printf("
    "); 
        
    }
    int main(void)
    {
        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; 
    }
    # include <stdio.h>
    
    //f函数可以输出任何一个一维数组的内容 
    void f(int * pArr,int len)
    {
        pArr[3] = 88;
    }
    int main(void)
    {
        int a[6] = {1,2,3,4,5,6};
        printf("%d
    ",a[3]);
        f(a,6);
        printf("%d
    ",a[3]);
        return 0; 
    }
    /*
    4
    88
    */
    指针变量的运算
                指针变量不能相加,不能相乘,也不能相除,只能相减
                如果两个指针变量指向的是同一块连续空间中的不同存储单元,则这两个指针变量才可以相减
    # include <stdio.h>
    
    
    int main(void)
    {
        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; 
    }
    一个指针变量到底占几个字节【非重点】
                        预备知识:
                            sizeof(数据类型)
                            功能:返回值就是该数据类型所占的字节数
                            例子:sizeof(int) = 4   sizeof(char)  =  1
                                    sizeof(double)  =  8
                            sizeof(变量名)
                            功能:返回值是该变量所占的字节数
                    假设p指向char类型变量(1个字节)
                    假设p指向char类型变量(4个字节)
       假设p指向char类型变量(8个字节)
            p q  r本身所占字节数是否一致?
                    答案:一致
    总结:
      1.一个指针变量,无论它所指向耳朵变量占几个字节
       该指针变量本身只占四个字节
     
      2.一个变量的地址使用该变量首字节的地址来表示
     
         指针和二维数组
      3.指针和函数
      4.指针和结构体
      5.多级指针
       
    //多级指针 
    # include <stdio.h>
    
    int main(void)
    {
        int i = 10;
        int *p = &i;
        int **q = &p;
        int ***r = &q;
        
        /*
            *r = q->**r = *q = p->***r = **q = *p = i
        */
        
        //r = &p;  //因为r是int ***类型,r只能存放int **类型变量的地址
        printf("i = %d
    ",***r);
         
        return 0;
    }
    //多级指针 
    # include <stdio.h>
    
    void f(int **q)  //*q就是p 
    {
        
    } 
    
    void g()
    {
        int i = 10;
        int *p = &i;
        f(&p);  //p是int *类型,&p是int ** 类型 
    }
    int main(void)
    {
        g(); 
         
        return 0;
    }
    专题:
       动态内存分配【重点难点】
    传统数组的缺点:
        1.数组的长度必须事先指定,且只能是常整数,不能是变量
            例子:
                int  a[5];   //OK
                int len = 5;int a[len];//error
        2.传统形式定义的数组,该数组的内存程序员无法手动释放
            在一个函数运行期间,系统为该函数中的数组所分配的空间会一直存在,直到该函数运行完毕时,数组的空间才会被系统释放
        3.数组的长度不能在函数运行的过程中动态的扩充或缩小
            数组的长度一旦定义,其长度就不能再更改
        4.A函数定义的数组在A函数运行期间可以被其他函数使用,但A函数运行完毕之后,A函数中的数组无法再被其他函数使用
            传统方式定义的数组不能跨函数使用
     
    为什么需要动态分配内存
        动态数组很好的解决了传统数组的这4个缺点
        传统数组也叫静态数组
               动态内存分配举例--动态数组的构造  
    /*
        malloc是memory(内存)  allocate(分配)的缩写 
    */
    
    # include <stdio.h>
    # include <malloc.h>  //不能省 
    int main(void)
    {
        int i = 5;  //分配了4个字节  静态分配
        int *p = (int *)malloc(4);//12行 
        /*
            1.要使用malloc函数,必须添加malloc.h这个头文件
            2. mallo0c函数只有一个形参,并且形参是整型
            3.4表示请求系统为本程序分配4个字节
            4.malloc函数只能返回第一个字节的地址
            5. 12行分配了8个字节,
                p变量占4个字节,p指向的内存也占4个字节 
            6.p本身所占的内存是静态分配的,p所指向的内存是动态分配的
             
        */ 
        *p = 5;//*p代表的就是一个int变量,
            //只不过*p这个整型变量的内存分配方式和11行的不同 
        
        free(p);  //free(p)表示把p所占的内存给释放掉 
                //    p本身的内存是静态的,不能由程序员手动释放 
        printf("同志们好!
    "); 
        return 0;
        
    }
    # include <stdio.h>
    # include <malloc.h> 
    int main(void)
    {
        int len;
        int *pArr;
        int i;
        //动态的构造一维数组 
        printf("请输入您要存放的元素的个数:");
        scanf("%d",&len);
        pArr = (int *)malloc(4 * len);
        //对一维数组进行操作 
        for(i = 0;i < len;++i) 
            scanf("%d",&pArr[i]);
            
        //对一维数组进行输出
        printf("一维数组的内容是:
    ");
        for(i = 0;i < len;++i)
            printf("%d
    ",pArr[i]);
            
        free(pArr);  //释放掉动态分配的数组 
        return 0;
    }
    静态内存和动态内存的比较
      静态内存是由系统自动分配,由系统自动释放
      静态内存是在栈分配的
      动态内存是由程序员手动分配,手动释放
      动态内存是在堆分配的
    跨函数使用内存的问题
      静态变量不能跨函数使用
    # include <stdio.h>
    
    void f(int **q)  //q也是个指针变量,
                    //无论q是什么类型的指针变量,都只占4个字节 
    {
        int i = 5;
        //*q等价于p q和**q都不等价于p 
        //*q = i;  //error  因为*q = i;等价于p = i,这是错误的
        *q = &i;  //p = &i; p = *q; --> *q = &i;
    }
    int main(void)
    {
        int *p;
        
        f(&p);
        //printf("%d
    ",*p); 
         //本语句语法没有问题,但逻辑有问题 ,它是静态分配的
        return 0;
    }

    动态内存可以跨函数使用

    # include <stdio.h>
    # include <malloc.h> 
    void f(int **q)
    {
        *q = (intn *)malloc(sizeof(int));
            //sizeof(数据类型)  返回值是该数据类型所占的字节
        **q = 5;  //*p = 5;
    }
    int main(void)
    {
        int *p;
        f(&p);
        printf("%d
    ",*p);  //没有错误,函数没有终止 ,因为是动态分配的
        return 0;
    }
  • 相关阅读:
    AutoCAD如何移动零件和缩放零件图
    AutoCAD如何输入文字
    AutoCAD如何设置A0A1图纸
    AutoCAD如何批量设置线宽
    AutoCAD如何快速标注零件序号
    AutoCAD如何将dwf转成dwg格式
    AutoCAD参照编辑期间不允许使用 SAVE 命令怎么办
    AutoCAD2004启动时出现fail to get CommcntrController的怎么办
    AutoCAD 样条曲线如何结束
    AutoIt3常见问题解答
  • 原文地址:https://www.cnblogs.com/pig1314/p/8653110.html
Copyright © 2011-2022 走看看