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表示常量
定义的时候是什么类型就一直是什么类型
指针数组+二维数组 (都需要解引用两次 但是不一样)
数组指针 可以指向二维数组 怎么定义数组指针 怎么赋值
用法 正确赋值之后 和二维数组是一样的
一行有多少个元素 存的什么类型的元素
代码笔记:
#include<stdio.h>
#include<stdlib.h>
/*--01
int max(int a, int b)
{
return a > b;//返回比较的结果 1或者0
} int fun(int x, int y, int z,int(*pMax)(int,int))//最后一个参数 函数指针 (形参函数指针)
{
return pMax(x, y);//用函数指针调用函数
}
*/ //排序 冒泡 选择 插入 桶排序 快速 希尔 堆排序 归并排序 //冒泡排序 思路 循环比较相邻的元素 大小关系和排序方向不和 交换两个元素
//从小到大排序 从左到右开始比较 如果第一个比第二个小 顺序不变 始终保持 左边小又变大
//每轮可以使得一个数字沉底 n个元素 只要循环n-1轮 int max(int a, int b)
{
return a > b;
}
int min(int a, int b)
{
return a < b;
} #if 0
void bull_sort(int arr[],int n) //冒牌排序 arr是存放数据的数组 n是数组中元素个数
{
int temp;//中间变量
for (int i = ; i < n - ; ++i) //循环n-1轮 每轮沉底一个数字 控制循环次数
{
//排序过程
for (int j = ; j < n-; ++j) //j<n&&j+1<n 防止越界 控制循环
{
if (arr[j] > arr[j + ]) //从小到大排序 前面元素比后面元素大 交换
{//从大到小的排序 前面的元素比后面的元素小 交换
temp = arr[j];
arr[j] = arr[j+];
arr[j+] = temp;//temp中间变量 用来交换
}
}
printf("第[%d]轮排序:", i);//第i轮排序
for (int k = ; k < ; ++k)
{
printf("%d\t", arr[k]);
}
printf("\n\n");
}
}
#endif //优化后的代码 运用函数指针
void bull_sort(int arr[], int n, int(*p)(int,int)) //函数指针 用来控制从小到大还是从大到小 冒牌排序 arr是存放数据的数组 n是数组中元素个数
{
int temp;//中间变量
for (int i = ; i < n - ; ++i) //循环n-1轮 每轮沉底一个数字 控制循环次数
{
//排序过程
//for (int j = 0; j < n-1; ++j) //j<n&&j+1<n 防止越界 控制循环
for (int j = ; j<n - -i;++j)//优化之后的算法 j<n - 1-i 可以减少比较次数
{
if (p(arr[j],arr[j + ])) //从小到大排序 前面元素比后面元素大 交换
{//从大到小的排序 前面的元素比后面的元素小 交换
temp = arr[j];
arr[j] = arr[j+];
arr[j+] = temp;//temp中间变量 用来交换
}
}
printf("第[%d]轮排序:", i);//第i轮排序
for (int k = ; k < ; ++k)
{
printf("%d\t", arr[k]);
}
printf("\n\n");
}
}
int main()
{
#if 0
double x;
int *p = &x;//如果定义一个double型的x 那么赋值给int*型p 就会报错
//int* 是指针的类型 int(*pArr)[] = &x;//这是一个数组指针类型 与定义的double型的是不相附的 所以会报错 //可以如下方式定义
int arr[];
int(*pArr)[] = &arr;//取一位数组的地址
//使用如下
(*pArr)[];//arr[0]的地址 pArr相当于&arr地址 --->*pArr 相当于arr arr[0] 相当于 (*pArr)[0]
//取变量地址 不会取数组地址--->很麻烦
#endif #if 0
//常用的方式
int *p;
p = arr;//常规定义方法 保存的是数组首元素的地址
*p = ;//相当于arr[0]=1;
p += ;//指针加减法是地址的加减 指针加一 地址加多少 要看指针指向变量的类型而定 指向下一个元素的地址 不是下标 指针加减之后还是指针
#endif #if 0
p = (int*)malloc(sizeof(int)* );//申请内存
p++;//p++之后不再指向原来的地址
free(p);//释放内存 运行后会报出一个错误 出现一个断点
#endif #if 0
int x;//const 常属性 不能修改
int *const p=&x; //指针常量 *表示指针 const表示常量 定义的时候必须赋值
//const修饰的p p不可以修改 *p可以修改 *p = ;//赋值 scanf也可以赋值
p++;//不能修改指向
scanf("%d", p);//scanf要用地址 用指针也可以 int const*q;//*在const后面 常量指针(指向常量 不能修改常量)
//*q不能修改 q可以修改 *q不能作为左值 q没有修改内容的权限 q = &x;
*q = ;//不能修改内容 *q不能作为左值
#endif #if 0
//指针数组 数组
//类型 数组名[数组大小]
int* arr[];//指针数组 表示数组中存放的是int*类型的变量
//存放指针的数组
//总共10个int* //数组指针
int(*parr)[];//数组指针 表示parr指针 指向数组的指针
//只有一个指针int(*)[10] //上面两个用法相近 但是意义不一样
//指针数组
for (int i = ; i < ; i++)
{
arr[i] = (int*)malloc(sizeof(int)* );//给10个指针元素赋值 sizeof求大小 malloc要申请的堆内存的大小 意思是申请20个字节的大小的空间
//注意下越界问题
}
int**pp = arr;//二级指针和指针数组对应
//赋值之后使用和指针数组是一样的 //占用的总内存 指针数组 10个int* 一个指针4字节 10*4+10*5*4=240字节 指针大小+堆区大小
//int brr[10][5] 10*5*4=200个字节
for (int i = ; i < ; i++)free(arr[i]);//循环释放内存
//数组存放在连续内存中
//申请堆内存的时候 单次申请的内存连续 多次申请的不一定连续
//申请堆内存后记得要释放
int dArr[][];//二维数组
int(*pdArr)[] = dArr;//赋值数组名 数组指针
//用法和二维数组一样的 都是解引用两次 //二级指针 和数组指针
//int **pp 可以用来对应一个指针数组名
//总结 指针数组名 二维数组名 二级指针 数组指针 都需要解引用两次 使用的时候比较相似 但是是有区别的
//malloc 返回指针的函数 指针函数
//函数指针 传参的时候用函数指针接收
//传参 调用函数 实参(函数名) 形参(函数指针) #endif //--01--fun(1, 2, 3, max);//z直接实参是函数名
#if 0
int test[] = {,,,,,,,,,};
printf("排序前:\n");
for (int i = ; i < ; ++i)
{
printf("%d\t", test[i]);//排序前
}
printf("\n\n"); printf("排序后:\n");
bull_sort(test, );
for (int i = ; i < ; ++i)
{
printf("%d\t",test[i]);//排序后
}
printf("\n\n"); getchar();
return ;
#endif int test[] = { , , , , , , , , , };
printf("测试一:\n");
printf("排序前:\n");
for (int i = ; i < ; ++i)
{
printf("%d\t", test[i]);//排序前
}
printf("\n\n"); printf("排序后:\n");
bull_sort(test, ,max);
for (int i = ; i < ; ++i)
{
printf("%d\t", test[i]);//排序后
}
printf("\n\n"); printf("测试二:\n");
printf("排序后:\n");
bull_sort(test, , min);
for (int i = ; i < ; ++i)
{
printf("%d\t", test[i]);//排序后
}
printf("\n\n"); getchar();
return ;
}
其中涉及到冒泡排序:
优化前的代码:
#include<stdio.h>
#include<stdlib.h> void bull_sort(int arr[],int n) //冒牌排序 arr是存放数据的数组 n是数组中元素个数
{
int temp;//中间变量
for (int i = ; i < n - ; ++i) //循环n-1轮 每轮沉底一个数字 控制循环次数
{
//排序过程
for (int j = ; j < n-; ++j) //j<n&&j+1<n 防止越界 控制循环
{
if (arr[j] > arr[j + ]) //从小到大排序 前面元素比后面元素大 交换
{//从大到小的排序 前面的元素比后面的元素小 交换
temp = arr[j];
arr[j] = arr[j+];
arr[j+] = temp;//temp中间变量 用来交换
}
}
printf("第[%d]轮排序:", i);//第i轮排序
for (int k = ; k < ; ++k)
{
printf("%d\t", arr[k]);
}
printf("\n\n");
}
} int main()
{
int test[] = {,,,,,,,,,};
printf("排序前:\n");
for (int i = ; i < ; ++i)
{
printf("%d\t", test[i]);//排序前
}
printf("\n\n"); printf("排序后:\n");
bull_sort(test, );
for (int i = ; i < ; ++i)
{
printf("%d\t",test[i]);//排序后
}
printf("\n\n"); getchar();
return ;
}
优化后的代码:
#include<stdio.h>
#include<stdlib.h> int max(int a, int b)
{
return a > b;
}
int min(int a, int b)
{
return a < b;
} void bull_sort(int arr[], int n, int(*p)(int,int)) //函数指针 用来控制从小到大还是从大到小 冒牌排序 arr是存放数据的数组 n是数组中元素个数
{
int temp;//中间变量
for (int i = ; i < n - ; ++i) //循环n-1轮 每轮沉底一个数字 控制循环次数
{
//排序过程
//for (int j = 0; j < n-1; ++j) //j<n&&j+1<n 防止越界 控制循环
for (int j = ; j<n - -i;++j)//优化之后的算法 j<n - 1-i 可以减少比较次数
{
if (p(arr[j],arr[j + ])) //从小到大排序 前面元素比后面元素大 交换
{//从大到小的排序 前面的元素比后面的元素小 交换
temp = arr[j];
arr[j] = arr[j+];
arr[j+] = temp;//temp中间变量 用来交换
}
}
printf("第[%d]轮排序:", i);//第i轮排序
for (int k = ; k < ; ++k)
{
printf("%d\t", arr[k]);
}
printf("\n\n");
}
} int main()
{
int test[] = { , , , , , , , , , };
printf("测试一:\n");
printf("排序前:\n");
for (int i = ; i < ; ++i)
{
printf("%d\t", test[i]);//排序前
}
printf("\n\n"); printf("排序后:\n");
bull_sort(test, ,max);
for (int i = ; i < ; ++i)
{
printf("%d\t", test[i]);//排序后
}
printf("\n\n"); printf("测试二:\n");
printf("排序后:\n");
bull_sort(test, , min);
for (int i = ; i < ; ++i)
{
printf("%d\t", test[i]);//排序后
}
printf("\n\n"); getchar();
return ;
}
2019-03-20 18:02:32
C++学习(二十三)(C语言部分)之 指针4的更多相关文章
- Salesforce LWC学习(二十三) Lightning Message Service 浅谈
本篇参考: https://trailhead.salesforce.com/content/learn/superbadges/superbadge_lwc_specialist https://d ...
- Flutter学习二之Dart语言介绍
上次我记录了Flutter的环境搭建,这次来简单记录一下Drat语言,Flutter是 Google推出并开源的移动应用开发框架,开发语言是Dart,那么Dart语言和其他的语言在语法上有上面区别呢, ...
- 前端学习(二十三)DOM操作,事件(笔记)
javascript 组成部分 1.ECMAScript javascript的核心解释器 2.DOM Document Object Modle 文 ...
- ElasticSearch7.3学习(二十三)----RestHighLevelClient Java api实现match_all、ids、match、term、multi_match、bool、filter、sort等不同的搜索方式
1.数据准备 首先创建book索引 PUT /book/ { "settings": { "number_of_shards": 1, "number ...
- Java开发学习(二十三)----SpringMVC入门案例、工作流程解析及设置bean加载控制
一.SpringMVC概述 SpringMVC是隶属于Spring框架的一部分,主要是用来进行Web开发,是对Servlet进行了封装.SpringMVC是处于Web层的框架,所以其主要的作用就是用来 ...
- ballerina 学习二十三 扩展ballerina
扩展ballerina 目前有三种方式: 扩展client connector的包 (数据库访问,基础设施,api) 扩展server listenner 绑定为不同的协议 添加新的注解到baller ...
- 渗透测试学习 二十三、常见cms拿shell
常见cms 良精.科讯.动易.aspcms.dz 米拓cms.phpcms2008.帝国cms.phpv9 phpweb.dedecms 良精 方法: 1.数据库备份拿shell 上传图片——点击数据 ...
- python学习二十三天函数的定义
在计算机编程中,函数就是可以重复调用,可以传递参数,减少代码的量,可以高效写出好的代码,提高软件的运行质量,下面简单讲述python函数的定义方式 1,函数的定义 函数的定义用关键词def 函数名跟 ...
- C++(二十三) — 内存泄漏及指针悬挂
1.内存泄漏 动态申请的内存空间没有正常释放,但也不能继续使用. ; pch1 = new char('A'); // 此处申请的空间未被释放. char *pch2 = new char; pch1 ...
- Java开发学习(二十四)----SpringMVC设置请求映射路径
一.环境准备 创建一个Web的Maven项目 参考Java开发学习(二十三)----SpringMVC入门案例.工作流程解析及设置bean加载控制中环境准备 pom.xml添加Spring依赖 < ...
随机推荐
- JAVA按数字,字母排序,但不包括大小写和汉字排序
public class ABC { public static void main(String[] args) { new ABC().sortStringArray(); } public vo ...
- Linux的安装包命令/yum 与 Rpm
1.Rpm安装包命令(以dhcp软件包为例)----Rpm安装软件包需要解决依赖性,因此特别麻烦(如图2被需要). rpm与yum安装的均为二进制软件包.类似于windows下载的软件包,可直接安装使 ...
- leetcode python 001
给定一个数组,和一个数字target,要求返回和为target的两个数组成员的下标. import numpy as npimport time #### 构造题目 , x数组大小x=100000l1 ...
- 2.6 C++通过引用来传递和返回类对象
参考:http://www.weixueyuan.net/view/6338.html 总结: C++语言中,由类声明的对象,和其它类型声明的变量一样,同样可以通过传值.引用和指针的方式作为函数的参数 ...
- java命令提示找不到或无法加载主类
使用java执行命令出现此错误 localhost:SocketDemo wangwei$ javac Server.java localhost:SocketDemo wangwei$ java S ...
- 201621123001 《Java程序设计》第6周学习总结
1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图或相关笔记,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰 ...
- Problem B 字符串类(I)
封装一个字符串类,用于存储字符串和处理的相关功能,支持以下操作: 1. STR::STR()构造方法:创建一个空的字符串对象. 2. STR::STR(const char *)构造方法:创建一个字符 ...
- js重写trim()方法
最近项目中出现去空格的需求,我本地是IE11,使用trim()函数的时候,是无法识别的.因此重写String的trim()方法. 1.要求 可以去除首位全角,半角空格. 2.对 能去除所有 Str ...
- 一个灵活的AssetBundle打包工具
尼尔:机械纪元 上周介绍了Unity项目中的资源配置,今天和大家分享一个AssetBundle打包工具.相信从事Unity开发或多或少都了解过AssetBundle,但简单的接口以及众多的细碎问题 ...
- [AOP] 之让人一脸蒙哔的面向切面编程
最近接触到了面向切面编程,看来很多的文档,算是有一点点了解了,趁自己还有点印象,先把它们给写出来 什么是AOP AOP(Aspect-Oriented Programming), 即 面向切面编程. ...