美文网首页
指针的概念

指针的概念

作者: 往事一块六毛八 | 来源:发表于2016-12-15 22:28 被阅读15次

    指针入门 ******

     int i = 123;
           //一般计算机中用16进制数来表示一个内存地址 
           printf("%#x\n",&i); 
           //int* int类型的指针变量  pointer指针  指针变量只能用来保存内存地址
           //用取地址符&i 把变量i的地址取出来 用指针变量pointer 保存了起来
           //此时我们可以说 指针pointer指向了 i的地址 
           int* pointer = &i;   
           printf("pointer的地址 = %#x\n",pointer);
           printf("*pointer的值%d\n",*pointer);
           *pointer = 456;//修改pointer的值
           printf("i的值是%d\n",i);
           system("pause"); 
    

    由于pointer存的是i的内存地址,多以对pointer的操作就是对变量i的操作*pointer在等号左边就是赋值操作,在等号右边是取值操作

    java zhong 两个值的交换操作
    ![IJUK6LYQGDJ_2]~D10%X0.png](https://img.haomeiwen.com/i2648920/33ec6258097a0db3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    • 指针常见错误
      • 声明了指针变量后 未初始化直接通过*p 进行赋值操作 运行时会报错
          • 未赋值的指针称为野指针
      • 指针类型错误 如int* p 指向了double类型的地址, 通过指针进行读取操作时,读取值会出错
    #include<stdio.h>    
    #include<stdlib.h>    
    /**
    */
    main(){  
             //野指针   指针使用之前要初始化 赋给它一个自己程序中声明的变量的地址
             //指针使用的时候要注意 int类型的指针要指向int类型的内存地址, double类型的指针要指向double类型的地址 ....
              //如果乱指会出bug 
             int i; 
             double d = 3.1415;
           int* pointer = &d;
           printf("pointer的值=%#x\n",pointer);
           printf("*pointer = %d\n",*pointer);
           system("pause"); 
           } 
    
    

    指针的练习

    Paste_Image.png
    • 值传递和引用传递(交换两个数的值)
      • 引用传递本质是把地址传递过去

      • 所有传递其实本质都是值传递,引用传递其实也是传递一个值,但是这个值是一个内存地址

          void swap(int* p, int* p2){
              int temp = *p;
              *p = *p2;
              *p2 = temp; 
          }
          main(){
              int i = 123;
              int j = 456;
              //将i, j的地址传递过去
              swap(&i,&j);
              printf("i = %d, j = %d", i, j);
          }
        
    Paste_Image.png
    • 返回多个值
      • 把地址作为参数传入函数中,当函数执行完毕时,参数的值就已经被修改了
    #include<stdio.h>    
    #include<stdlib.h>    
    /**
    "*" 的几个含义   int*  声明一个int类型的指针变量
                x * y  乘法运算
                int* pointer;
                *pointer; 取出指针变量pointer 中保存的内存地址对应的内存中的值 
    */
     function(int* pointer, int* pointer2){
         *pointer *= 2;
         *pointer2 *=2;
        }
    main(){    
          int i =1;
          int j = 2;
          //char c;
          function(&i,&j);
          printf("i = %d,j = %d\n",i,j);
           system("pause"); 
           } 
    
    

    多级指针

    • int* p; int 类型的一级指针 int** p2; int 类型的二级指针

    • 二级指针变量只能保存一级指针变量的地址

    • 有几个* 就是几级指针 int*** 三级指针

    • 通过int类型三级指针 操作int类型变量的值 ***p

            int i = 123;
            //int类型一级指针 
            int* p = &i;
            //int 类型 二级指针 二级指针只能保存一级指针的地址 
            int** p2 = &p;
            //int 类型 三级指针  三级指针只能保存二级指针的地址 
            int*** p3 = &p2;
            //通过p3 取出 i的值
            printf("***p3 = %d\n", ***p3);
      
    • 多级指针案例 取出子函数中临时变量的地址

    Paste_Image.png
    #include<stdio.h>    
    #include<stdlib.h>    
    /**
    多级指针 数星星  有几个星就是几级指针 取值通过三级指针拿到最初的变量的值 ***point3 
    */
    main(){    
          int i = 123;
          //int类型的一级指针 
          int* pointer = &i;
          //int类型的二级指针 二级指针只能保存一级指针的地址 
          int** pointer2 = &pointer; 
          //int类型的三级指针 
          int*** pointer3 = &pointer2; 
          printf("***pointer3 = %d\n",***pointer3);
           system("pause"); 
           } 
    
    

    数组和指针的关系

    • 数组占用的内存空间是连续的
    • 数组变量保存的是第0个元素地址,也就是首地址
    • *(p + 1):指针位移一个单位,一个单位是多少个字节,取决于指针的类型
    #include<stdio.h>    
    #include<stdlib.h>    
    /**
    数组实际上就是一块连续的内存空间 
    */
    main(){
             
      // char array[] = {'a','b','c','d','\0'};
       int array[] = {1,2,3,4};
       printf("array[0]的地址%#x\n",&array[0]);
       printf("array[1]的地址%#x\n",&array[1]);
       printf("array[2]的地址%#x\n",&array[2]);
       printf("array[3]的地址%#x\n",&array[3]);
       printf("array的地址%#x\n",&array);
       //数组变量名的地址实际上是第一个元素的地址
       char* pointer = &array;
        //int* pointer = &array;
        char array2[] =  "hello from c"
    //c语言当中的char类型的数组就是c语言当中的字符串,现在*pointer存的是数组的首地址,printf("%s\n",pointer2);是字符串的输出,所以从char数组的首地址开始输出字符串
       char* pointer2="hello from c";
       //printf("%s\n",pointer2);
       /*
       printf("*(pointer+0)=%c\n",*(pointer+0));
       printf("*(pointer+0)=%c\n",*(pointer+1));
       printf("*(pointer+0)=%c\n",*(pointer+2));
       printf("*(pointer+0)=%c\n",*(pointer+3));
       */
       printf("*(pointer+0)=%d\n",*(pointer+0));
       printf("*(pointer+1)=%d\n",*(pointer+1));
       printf("*(pointer+2)=%d\n",*(pointer+2));
       printf("*(pointer+3)=%d\n",*(pointer+3));
        
           system("pause"); 
           } 
    
    

    指针的长度

    • 不管变量的类型是什么,它的内存地址的长度一定是相同的
    • 类型不同只决定变量占用的内存空间不同
    • 32位环境下,内存地址长度都是4个字节,所以指针变量长度只需4个字节即可
    • 区分指针类型是为了指针位移运算方便
    #include<stdio.h>    
    #include<stdlib.h>    
    /**
    32位操作系统地址总线是32位   4个字节的变量来保存32位操作系统的内存地址 1byte 8位  4*8=32 
    32位操作系统 指针变量占4个字节
    64位操作系统 指针变量占8个字节 
    */
    main(){    
          int* pointer;
          double* pointerD; 
          printf("int类型的指针变量占%d个字节\n",sizeof(pointer));
          printf("double类型的指针变量占%d个字节\n",sizeof(pointerD));
           system("pause"); 
           } 
    
    
    #include<stdio.h>    
    #include<stdlib.h>    
    /**
    main函数获取子函数中临时变量的地址 
    */
    function(int** pointer){
       int i = 123;
        *pointer = &i;  
        printf("i的地址%#x\n",&i);    
              }
    
    main(){    
          int* pointer1;
          function(&pointer1);
          printf("pointer1的值%#x\n",pointer1);
           system("pause"); 
           } 
    
    
    Paste_Image.png

    堆栈概念 静态内存分配 动态内存分配

    • 栈内存
      • 系统自动分配
      • 系统自动销毁
      • 连续的内存区域
      • 向低地址扩展
      • 大小固定
      • 栈上分配的内存称为静态内存
    • 静态内存分配
    • 子函数执行完,子函数中的所有局部变量都会被销毁,内存释放,但内存地址不可能被销毁,只是地址上的值没了
    
    
    
    #include<stdio.h>    
    #include<stdlib.h>    
    /**
    栈内存 系统统一分配统一回收  
    静态内存分配 栈内存大小固定的 内存地址是连续的 
    */
    int* getData(){
         int array[] ={1,2,3,4,5};
         printf("%#x\n",&array);
         return &array;
         }
    int* getData2(){
         int array[] ={5,4,3,2,1};
         printf("%#x\n",&array);
         return &array;
         }
    
    main(){    
         int* pointer = getData();
         getData2();
         printf("%d,%d,%d\n",*(pointer+0),*(pointer+1),*(pointer+2));
         printf("%d,%d,%d\n",*(pointer+0),*(pointer+1),*(pointer+2));
         printf("%#x\n",pointer);
           system("pause"); 
           } 
    
    • 堆内存
      • 程序员手动分配
        • java:new
        • c:malloc
      • 空间不连续
      • 大小取决于系统的虚拟内存
      • C:程序员手动回收free
      • java:自动回收
      • 堆上分配的内存称为动态内存
    #include<stdio.h>    
    #include<stdlib.h>    
    /**
    java new对象就会申请一块堆内存
    c   malloc memory allocation 内存分配 
    c的堆内存 程序员手动申请手动释放  malloc
    free 
    申请一块堆内存 动态内存分配 
    堆内存 不连续的 
    堆内存大小不固定 取决机器的状态 
    */
    main(){ 
            //malloc 接收的参数 申请内存大小 返回一个内存地址值 申请到的也是一块连续的内存空间   
          int* pointer = malloc(sizeof(int)*5);
          *(pointer+0) = 1;
          *(pointer+1) = 2;
          *(pointer+2) = 3;
          *(pointer+3) = 4;
          *(pointer+4) = 5;
          //C for 循环 循环的临时变量i 要先声明再使用 
          int i;
          for(i = 0;i<5;i++){
                  printf("第%d个元素的值= %d\n",i,*(pointer+i));
                  }
          free(pointer);
          printf("第一个元素的值%d\n",*(pointer+0));
           system("pause"); 
           } 
    
    
    #学生管理系统#
    #include<stdio.h>    
    #include<stdlib.h>    
    /**
    保存班级人数
    申请一块堆内存保存学生的学号
    来了几个插班生
    扩展一下堆内存
    保存插班生的学号 
    realloc re- 
    */
    main(){ 
           printf("请输入班级的人数:");
           int count;
           scanf("%d",&count);
           //申请一块堆内存
           int* pointer = malloc(sizeof(int)*count);
           int i;
           for(i = 0;i<count;i++){
                 printf("请输入第%d个学生的学号:",i+1);
                 scanf("%d", pointer+i);
                 }  
           for(i = 0;i<count;i++){
                 printf("第%d个学生的学号是:%d\n",i+1,*(pointer+i));  
                 } 
           printf("请输入插班生的人数:");
           //声明一个变量increment用来保存 插班生的人数 
           int increment;
           //接受用户的输入 
           scanf("%d",&increment);
           //重新申请一块足够大的内存 
           //如果 malloc申请到的内存后面还有足够的空间 realloc会在malloc申请的内存空间后继续申请足够大的内存空间
           //如果 malloc申请到的内存后面没有足够的空间 realloc会找到一块足够大的堆内存 并且把 malloc申请到的内存中的值复制过来 
          pointer = realloc(pointer,sizeof(int)*(count+increment));
          for(i = count;i<count+increment;i++){
                 printf("请输入第%d个学生的学号:",i+1);
                 scanf("%d", pointer+i);
                }
          for(i = count;i<count+increment;i++){
                printf("第%d个学生的学号是:%d\n",i+1,*(pointer+i));  
                }
           system("pause"); 
           } 
    

    结构体

    • 结构体中的属性长度会被自动补齐,这是为了方便指针位移运算
    • 结构体中不能定义函数,可以定义函数指针
    • 程序运行时,函数也是保存在内存中的,也有一个地址
    • 结构体中只能定义变量
    • 函数指针其实也是变量,它是指针变量
    • 函数指针的定义 返回值类型(*变量名)(接收的参数);
    • 函数指针的赋值: 函数指针只能指向跟它返回值和接收的参数相同的函数
    #include<stdio.h>    
    #include<stdlib.h>    
    /**
    c结构体 类似java的class  struct来声明c的结构体 
    结构体的大小大于等于结构体中每一变量的占字节数的和
     结构体的大小是最大的那个变量所占字节数的整数倍 
     C结构体中不能定义函数  
     
     函数指针的定义   返回值(*函数指针变量名字)(返回值); 
     -> 间接引用运算符   
    */
    void study(){
               printf("good good study!\n");
               }
    typedef struct Student{
          int age;  //8
          int score;  // 4
          char sex;   //1
          void(*studypointer)();
          } stud;
    main(){    
     stud stu = {18,100,'f'};
     stu.studypointer = &study;
     stu.studypointer();
     struct Student* stuPointer = &stu;//结构体指针
     printf("*stuPointer.age = %d\n",(*stuPointer).age);
     (*stuPointer).sex ='m';
     printf("stu.sex = %c\n",stu.sex);
     printf("stuPointer->age = %d",stuPointer->age);
     //printf("stu.age = %hd\n",stu.age);
     //printf("stu.score = %d\n",stu.score);
     //printf("stu.sex = %c\n",stu.sex);
    // printf("结构体student占%d个字节\n",sizeof(stu));
           system("pause"); 
           } 
    
    

    联合体

    • 长度等于联合体中定义的变量当中最长的那个
    • 联合体只能保存一个变量的值
    • 联合体共用同一块内存
    #include<stdio.h>    
    #include<stdlib.h>    
    /**
    联合体占字节数取决于 其中成员 占内存空间最大的那一个 
    */
    union u{
          int num; //4
          double d; //8
          }
    main(){    
       union u u1;
       u1.num = 123;
       u1.d = 123.456;
       printf("union占%d个字节\n",sizeof(u1));
       printf("u1.num = %d\n",u1.num);
           system("pause"); 
           } 
    
    

    相关文章

      网友评论

          本文标题:指针的概念

          本文链接:https://www.haomeiwen.com/subject/spwgmttx.html