cy语言之指针3

指针是一个变量,它存储的是另一个变量的内存地址,而不是数据本身。通过指针可以间接访问和修改它所指向的变量。

数据类型 *指针变量名;

  • 数据类型:指针所指向的变量的类型(如 intcharfloat 等)。

  • *:表示这是一个指针变量。

  • 指针变量名:符合C语言命名规则的标识符。

int *p; // 定义一个指向 int 类型变量的指针 p

char *q; // 定义一个指向 char 类型变量的指针 q

float *r; // 定义一个指向 float 类型变量的指针 r

关键操作符

  • 取地址运算符 &:获取一个变量的内存地址。

  • 解引用运算符 *:访问指针所指向地址中存储的值。

%p:地址格式说明符(以十六进制打印指针中存储的地址值。)

虽然%d也能打印地址但是会报警,虽然不会报错,如下:

注意事项

  • 指针必须初始化,否则指向未知地址(野指针),可能导致程序崩溃。

  • 不能对未分配有效地址的指针解引用。

  • 指针本身也有地址,可以定义指向指针的指针(二级指针)。

指针数组:

指针数组是指一个数组,其中的每个元素都是一个指针变量。它常用于存储多个地址(例如多个字符串、多个数组的起始地址等)。

数据类型 *数组名数组长度;

  • 数据类型:指针所指向的数据类型。

  • *:表示数组元素是指针。

  • 数组名:标识符。

  • 数组长度:元素个数。

p+i == &arri

*(p + i)) == *(arr+i) == arri

指针p通过加减1,来访问地址的值。

数组的值是通过下标也是索引来进行访问的。

数组就是数组,是一块连续的空间(数组的大熊啊和数组元素的个数和元素类型都有关系。)

指针(变量)就是指针(变量),是一个变量(4/8个字节)

数组名是地址,是首元素的地址

可以使用指针来访问数组

arri == *(arr+i) == *(i+arr) == iarr

\[\] 下标引用符 相当于 加减 1+2 == 2+1 ,所以arri==iarr,但是一般都默认写为arri.

数组传参的本质是传递了数组首元素的地址,所以形参访问的数组和实参的数组是同一个数组的。

形参的数组是不会单独在创建数组空间的,所以形参的数组是可以省略掉数组大小的。

正确写法如下:

cs 复制代码
#include <stdio.h>
void Print(int* p, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{

		printf("%d ", *(p + i));
	}
}

int main()
{
	int arr[5] = { 1,2,3,4,5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	Print(arr,sz);//arr数组名就是数组首元素的地址。
	return 0;
}

冒泡排序

冒泡排序的核⼼思想就是:两两相邻的元素进⾏⽐较。

cs 复制代码
#include<stdio.h>
void bubble_sort(int arr[], int sz)//参数接收数组元素个数
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)//5个数,进行4次排序
	{
		int j = 0;
		for (j = 0; j < sz - i - 1; j++)//每一次排序确定一个数。
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}
int main()
{
	int arr[] = { 3,1,7,5,8,9,0,2,4,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}
cs 复制代码
//⽅法2 - 优化
void bubble_sort(int arr[], int sz)//参数接收数组元素个数
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int flag = 1;//假设这⼀趟已经有序了
		int j = 0;
		for (j = 0; j < sz - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				flag = 0;//发⽣交换就说明,⽆序
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
		if (flag == 1)//这⼀趟没交换就说明已经有序,后续⽆序排序了
			break;
	}
}
int main()
{
	int arr[] = { 3,1,7,5,8,9,0,2,4,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

⼆级指针

指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪⾥?

&a:变量a的地址 0x100

p:指针p的值(存的就是&a)0x100

*p:就是值 10,因为p指向的是a的地址,*p解引用后就得到了值。

*pp :取pp指向的内容,就是p的值 0x100 pp指向的是p,所以*pp就是解引用得到pp所指向的值,是p,而p是地址,想要得到数值,必须在解引用一次。

pp: 指针pp自己的地址 0x200

**pp:两次解引用,得到a值。,此代码中把%p改为%d,就可得到10。

就相当于你想睡觉,得先进大门,在进卧室门,才能睡觉,而大门是pp,卧室门是p,睡觉是a,那么你在大门第一次解引用,得到的是你卧室门的地址,第二次解引用你才能睡觉;如果你直接在卧室门,那么你只需要解引用一次,就可以睡觉了。

指针数组模拟⼆维数组

cs 复制代码
#include <stdio.h>
int main()
{
int arr1[] = {1,2,3,4,5};
int arr2[] = {2,3,4,5,6};
int arr3[] = {3,4,5,6,7};
//数组名是数组⾸元素的地址,类型是int*的,就可以存放在parr数组中
int* parr[3] = {arr1, arr2, arr3};
int i = 0;
int j = 0;
for(i=0; i<3; i++)
{
for(j=0; j<5; j++)
{
printf("%d ", parr[i][j]);
}
printf("\n");
}
return 0;
}

parri是访问parr数组的元素,parri找到的数组元素指向了整型⼀维数组,parri j就是整型⼀维数组中的元素。

上述的代码模拟出⼆维数组的效果,实际上并⾮完全是⼆维数组,因为每⼀⾏并⾮是连续的。

相关推荐
刘马想放假2 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
北域码匠3 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
Darling噜啦啦10 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
小小工匠11 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾11 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
Qres82111 天前
算法复键——树状数组
数据结构·算法
牛油果子哥q11 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
凌波粒11 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
WL学习笔记11 天前
单项不带头不循环链表
数据结构·链表
小糯米60111 天前
JS 数组
数据结构·算法·排序算法