C++学习(二十三)(C语言部分)之 指针4

时间:2023-03-10 04:47:49
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表示常量

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

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

C++学习(二十三)(C语言部分)之 指针4

C++学习(二十三)(C语言部分)之 指针4

代码笔记:

 #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