zoukankan      html  css  js  c++  java
  • C++学习(二十三)(C语言部分)之 指针4

    指针
    指针 存放地址 只能存放地址
    使用
    &取地址运算符 *取值 解引用运算符
    malloc 申请堆内存 free释放堆内存


    1.1 指针 存放的地址(变量地址 常量区的地址 堆区内存首地址 数组首地址 指针变量的地址 函数地址)
    1.指针 也是变量 指针也有类型
    int *p; //定义的时候 去掉变量名 剩下的就是类型
    int * 类型

    存放什么类型的变量地址 int (去掉*p之后 剩下的就是存放的地址中变量的类型)

    二级指针
    int **pp;
    pp的类型 int**
    pp指向的数据类型 存放int*类型的 变量地址

    int(*)[5];//数组指针
    int(*)[5]//指针l类型
    int[5] //指向的数组的地址

    定义是定义 使用是使用 是分开的
    pArr[i][j] *(*(pArr+i)+j) 使用的时候这是等价的 但定义的时候不一样

    重点
    1.指针类型
    2.指针指向数据的类型
    3.指针指向什么数据

    1.2 指针加减
    1.指针+int 指针-int类型
    p+1 让指针指向下一个元素
    2.p++ p--
    3.指针和指针相减 的道到的值距离

    //指针相加、相乘、相除 没有意义

    如果不清楚指针移动之后 指向什么区域 就不要对指针++或者--
    特别是申请内存的时候(不要随便移动这个指向堆内存首地址的指针)

    *(p+i) p[i] 两个内部实现是一样的


    1.3 常用的指针
    1.指针常量
    2.常量指针

    3.指针数组
    4.数组指针

    5.指针函数
    6.函数指针


    XX指针 XX是修饰 常量指针 是指:指向常量的指针

    指针XX 指针是修饰 指针常量 是指:类型是指针的常量
    指针函数 函数类型(返回值类型)是指针的函数


    指针常量
    int *const p; //*表示指针 const表示常量

    定义的时候是什么类型就一直是什么类型

    指针数组+二维数组 (都需要解引用两次 但是不一样)
    数组指针 可以指向二维数组 怎么定义数组指针 怎么赋值
    用法 正确赋值之后 和二维数组是一样的
    一行有多少个元素 存的什么类型的元素

    代码笔记:

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 /*--01
      4 int max(int a, int b)
      5 {
      6     return a > b;//返回比较的结果 1或者0
      7 }
      8 
      9 int fun(int x, int y, int z,int(*pMax)(int,int))//最后一个参数 函数指针 (形参函数指针)
     10 {
     11     return pMax(x, y);//用函数指针调用函数
     12 }
     13 */
     14 
     15 //排序  冒泡 选择 插入 桶排序 快速 希尔 堆排序 归并排序
     16 
     17 //冒泡排序   思路 循环比较相邻的元素 大小关系和排序方向不和 交换两个元素  
     18 //从小到大排序  从左到右开始比较 如果第一个比第二个小 顺序不变 始终保持 左边小又变大
     19 //每轮可以使得一个数字沉底  n个元素 只要循环n-1轮
     20 
     21 int max(int a, int b)
     22 {
     23     return a > b;
     24 }
     25 int min(int a, int b)
     26 {
     27     return a < b;
     28 }
     29 
     30 #if 0
     31 void bull_sort(int arr[],int n)  //冒牌排序 arr是存放数据的数组 n是数组中元素个数
     32 {
     33     int temp;//中间变量
     34     for (int i = 0; i < n - 1; ++i)  //循环n-1轮 每轮沉底一个数字 控制循环次数
     35     {
     36         //排序过程
     37         for (int j = 0; j < n-1; ++j)  //j<n&&j+1<n   防止越界  控制循环
     38         {
     39             if (arr[j] > arr[j + 1])  //从小到大排序 前面元素比后面元素大 交换
     40             {//从大到小的排序 前面的元素比后面的元素小 交换
     41                 temp = arr[j];
     42                 arr[j] = arr[j+1];
     43                 arr[j+1] = temp;//temp中间变量 用来交换
     44             }
     45         }
     46         printf("第[%d]轮排序:", i);//第i轮排序
     47         for (int k = 0; k < 10; ++k)
     48         {
     49             printf("%d	", arr[k]);
     50         }
     51         printf("
    
    ");
     52     }
     53 }
     54 #endif
     55 
     56 //优化后的代码 运用函数指针
     57 void bull_sort(int arr[], int n, int(*p)(int,int))  //函数指针 用来控制从小到大还是从大到小 冒牌排序 arr是存放数据的数组 n是数组中元素个数
     58 {
     59     int temp;//中间变量
     60     for (int i = 0; i < n - 1; ++i)  //循环n-1轮 每轮沉底一个数字 控制循环次数
     61     {
     62         //排序过程
     63         //for (int j = 0; j < n-1; ++j)  //j<n&&j+1<n   防止越界  控制循环
     64         for (int j = 0; j<n - 1-i;++j)//优化之后的算法 j<n - 1-i  可以减少比较次数
     65         {
     66             if (p(arr[j],arr[j + 1]))  //从小到大排序 前面元素比后面元素大 交换
     67             {//从大到小的排序 前面的元素比后面的元素小 交换
     68                 temp = arr[j];
     69                 arr[j] = arr[j+1];
     70                 arr[j+1] = temp;//temp中间变量 用来交换
     71             }
     72         }
     73         printf("第[%d]轮排序:", i);//第i轮排序
     74         for (int k = 0; k < 10; ++k)
     75         {
     76             printf("%d	", arr[k]);
     77         }
     78         printf("
    
    ");
     79     }
     80 }
     81 int main()
     82 {
     83 #if 0
     84     double x;
     85     int *p = &x;//如果定义一个double型的x 那么赋值给int*型p 就会报错    
     86     //int* 是指针的类型
     87     
     88     int(*pArr)[5] = &x;//这是一个数组指针类型 与定义的double型的是不相附的 所以会报错
     89     
     90     //可以如下方式定义
     91     int arr[5];
     92     int(*pArr)[5] = &arr;//取一位数组的地址
     93     //使用如下
     94     (*pArr)[0];//arr[0]的地址  pArr相当于&arr地址  --->*pArr 相当于arr  arr[0] 相当于 (*pArr)[0]
     95     //取变量地址 不会取数组地址--->很麻烦
     96 #endif
     97 
     98 #if 0
     99     //常用的方式
    100     int *p;
    101     p = arr;//常规定义方法 保存的是数组首元素的地址
    102     *p = 1;//相当于arr[0]=1;
    103     p += 4;//指针加减法是地址的加减 指针加一 地址加多少 要看指针指向变量的类型而定  指向下一个元素的地址 不是下标  指针加减之后还是指针
    104 #endif
    105 
    106 #if 0
    107     p = (int*)malloc(sizeof(int)* 10);//申请内存
    108     p++;//p++之后不再指向原来的地址
    109     free(p);//释放内存     运行后会报出一个错误 出现一个断点
    110 #endif
    111 
    112 #if 0
    113     int x;//const 常属性 不能修改
    114     int *const p=&x; //指针常量 *表示指针  const表示常量 定义的时候必须赋值
    115     //const修饰的p  p不可以修改 *p可以修改
    116 
    117     *p = 2;//赋值  scanf也可以赋值
    118     p++;//不能修改指向
    119     scanf("%d", p);//scanf要用地址 用指针也可以
    120 
    121 
    122     int const*q;//*在const后面 常量指针(指向常量 不能修改常量)
    123     //*q不能修改 q可以修改 *q不能作为左值 q没有修改内容的权限
    124     
    125     q = &x;
    126     *q = 23;//不能修改内容   *q不能作为左值
    127 #endif
    128 
    129 #if 0
    130     //指针数组 数组
    131     //类型 数组名[数组大小]
    132     int* arr[10];//指针数组  表示数组中存放的是int*类型的变量
    133     //存放指针的数组
    134     //总共10个int*
    135 
    136     //数组指针
    137     int(*parr)[10];//数组指针  表示parr指针  指向数组的指针
    138     //只有一个指针int(*)[10]
    139 
    140     //上面两个用法相近 但是意义不一样
    141     //指针数组
    142     for (int i = 0; i < 10; i++)
    143     {
    144         arr[i] = (int*)malloc(sizeof(int)* 5);//给10个指针元素赋值  sizeof求大小  malloc要申请的堆内存的大小  意思是申请20个字节的大小的空间
    145     //注意下越界问题
    146     }
    147     int**pp = arr;//二级指针和指针数组对应
    148     //赋值之后使用和指针数组是一样的
    149 
    150     //占用的总内存  指针数组 10个int*  一个指针4字节 10*4+10*5*4=240字节  指针大小+堆区大小
    151     //int brr[10][5]  10*5*4=200个字节
    152     for (int i = 0; i < 10; i++)free(arr[i]);//循环释放内存
    153     //数组存放在连续内存中
    154     //申请堆内存的时候 单次申请的内存连续 多次申请的不一定连续
    155     //申请堆内存后记得要释放
    156     int dArr[10][5];//二维数组
    157     int(*pdArr)[5] = dArr;//赋值数组名 数组指针
    158     //用法和二维数组一样的  都是解引用两次
    159 
    160     //二级指针 和数组指针
    161     //int **pp 可以用来对应一个指针数组名
    162     //总结 指针数组名 二维数组名 二级指针 数组指针 都需要解引用两次 使用的时候比较相似 但是是有区别的
    163     //malloc  返回指针的函数 指针函数
    164     //函数指针 传参的时候用函数指针接收
    165     //传参 调用函数  实参(函数名)  形参(函数指针)
    166 
    167 #endif
    168 
    169     //--01--fun(1, 2, 3, max);//z直接实参是函数名
    170 #if    0
    171     int test[10] = {43,21,78,98,12,23,56,67,99,10};
    172     printf("排序前:
    ");
    173     for (int i = 0; i < 10; ++i)
    174     {
    175         printf("%d	", test[i]);//排序前
    176     }
    177     printf("
    
    ");
    178     
    179     printf("排序后:
    ");
    180     bull_sort(test, 10);
    181     for (int i = 0; i < 10; ++i)
    182     {
    183         printf("%d	",test[i]);//排序后
    184     }
    185     printf("
    
    ");
    186     
    187     getchar();
    188     return 0;
    189 #endif
    190 
    191     int test[10] = { 43, 21, 78, 98, 12, 23, 56, 67, 99, 10 };
    192     printf("测试一:
    ");
    193     printf("排序前:
    ");
    194     for (int i = 0; i < 10; ++i)
    195     {
    196         printf("%d	", test[i]);//排序前
    197     }
    198     printf("
    
    ");
    199 
    200     printf("排序后:
    ");
    201     bull_sort(test, 10,max);
    202     for (int i = 0; i < 10; ++i)
    203     {
    204         printf("%d	", test[i]);//排序后
    205     }
    206     printf("
    
    ");
    207     
    208     printf("测试二:
    ");
    209     printf("排序后:
    ");
    210     bull_sort(test, 10, min);
    211     for (int i = 0; i < 10; ++i)
    212     {
    213         printf("%d	", test[i]);//排序后
    214     }
    215     printf("
    
    ");
    216 
    217     getchar();
    218     return 0;
    219 }

    其中涉及到冒泡排序:

    优化前的代码:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 
     4 void bull_sort(int arr[],int n)  //冒牌排序 arr是存放数据的数组 n是数组中元素个数
     5 {
     6     int temp;//中间变量
     7     for (int i = 0; i < n - 1; ++i)  //循环n-1轮 每轮沉底一个数字 控制循环次数
     8     {
     9         //排序过程
    10         for (int j = 0; j < n-1; ++j)  //j<n&&j+1<n   防止越界  控制循环
    11         {
    12             if (arr[j] > arr[j + 1])  //从小到大排序 前面元素比后面元素大 交换
    13             {//从大到小的排序 前面的元素比后面的元素小 交换
    14                 temp = arr[j];
    15                 arr[j] = arr[j+1];
    16                 arr[j+1] = temp;//temp中间变量 用来交换
    17             }
    18         }
    19         printf("第[%d]轮排序:", i);//第i轮排序
    20         for (int k = 0; k < 10; ++k)
    21         {
    22             printf("%d	", arr[k]);
    23         }
    24         printf("
    
    ");
    25     }
    26 }
    27 
    28 int main()
    29 {
    30     int test[10] = {43,21,78,98,12,23,56,67,99,10};
    31     printf("排序前:
    ");
    32     for (int i = 0; i < 10; ++i)
    33     {
    34         printf("%d	", test[i]);//排序前
    35     }
    36     printf("
    
    ");
    37     
    38     printf("排序后:
    ");
    39     bull_sort(test, 10);
    40     for (int i = 0; i < 10; ++i)
    41     {
    42         printf("%d	",test[i]);//排序后
    43     }
    44     printf("
    
    ");
    45     
    46     getchar();
    47     return 0;
    48 }

    优化后的代码:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 
     4 int max(int a, int b)
     5 {
     6     return a > b;
     7 }
     8 int min(int a, int b)
     9 {
    10     return a < b;
    11 }
    12 
    13 void bull_sort(int arr[], int n, int(*p)(int,int))  //函数指针 用来控制从小到大还是从大到小 冒牌排序 arr是存放数据的数组 n是数组中元素个数
    14 {
    15     int temp;//中间变量
    16     for (int i = 0; i < n - 1; ++i)  //循环n-1轮 每轮沉底一个数字 控制循环次数
    17     {
    18         //排序过程
    19         //for (int j = 0; j < n-1; ++j)  //j<n&&j+1<n   防止越界  控制循环
    20         for (int j = 0; j<n - 1-i;++j)//优化之后的算法 j<n - 1-i  可以减少比较次数
    21         {
    22             if (p(arr[j],arr[j + 1]))  //从小到大排序 前面元素比后面元素大 交换
    23             {//从大到小的排序 前面的元素比后面的元素小 交换
    24                 temp = arr[j];
    25                 arr[j] = arr[j+1];
    26                 arr[j+1] = temp;//temp中间变量 用来交换
    27             }
    28         }
    29         printf("第[%d]轮排序:", i);//第i轮排序
    30         for (int k = 0; k < 10; ++k)
    31         {
    32             printf("%d	", arr[k]);
    33         }
    34         printf("
    
    ");
    35     }
    36 }
    37 
    38 int main()
    39 {
    40     int test[10] = { 43, 21, 78, 98, 12, 23, 56, 67, 99, 10 };
    41     printf("测试一:
    ");
    42     printf("排序前:
    ");
    43     for (int i = 0; i < 10; ++i)
    44     {
    45         printf("%d	", test[i]);//排序前
    46     }
    47     printf("
    
    ");
    48 
    49     printf("排序后:
    ");
    50     bull_sort(test, 10,max);
    51     for (int i = 0; i < 10; ++i)
    52     {
    53         printf("%d	", test[i]);//排序后
    54     }
    55     printf("
    
    ");
    56     
    57     printf("测试二:
    ");
    58     printf("排序后:
    ");
    59     bull_sort(test, 10, min);
    60     for (int i = 0; i < 10; ++i)
    61     {
    62         printf("%d	", test[i]);//排序后
    63     }
    64     printf("
    
    ");
    65 
    66     getchar();
    67     return 0;
    68 }

    2019-03-20  18:02:32

  • 相关阅读:
    1509 -- Glass Beads POJ
    1043: [HAOI2008]下落的圆盘
    面向对象的特性一:封装性
    java的值传递机制
    可变参数的形参方法
    方法的重载
    类及对象
    面向对象
    数组的常用算法问题
    数组的常见异常
  • 原文地址:https://www.cnblogs.com/Yuuki-/p/10566587.html
Copyright © 2011-2022 走看看