指针

指针变量定义格式

在这里插入图片描述

查询数据

在这里插入图片描述

存储数据

在这里插入图片描述

// 利用指针去获取变量中的数据 /存储数据
	int a = 10;

	// 1.定义一个指针去指向变量a
	int* p = &a;
	// 2.利用指针去获取变量中的数据
	printf("%d\n",*p);//10
	// 3.利用指针去存储数据 /修改数据
	*p = 200;
	// 4.输出打印
	printf("%d\n",*p);//200
	printf("%d\n", a);//200

指针的使用细节

在这里插入图片描述

	char c = 'a';
	char* p1 = &c;

	long long n = 100;
	long long* p2 = &n;

	printf("%zu\n", sizeof(p1));
	printf("%zu\n", sizeof(p2));

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

小结

在这里插入图片描述
在这里插入图片描述

指针的作用

在这里插入图片描述

操作其他函数中的变量

在这里插入图片描述

#include <stdio.h>
void swap(int num1, int num2);
int main() {
	// 1.定义两个变量
	int a = 10;
	int b = 20;
	// 2.调用swap函数
	printf("调用前:%d %d\n",a,b);//10 20
	swap(a,b);//仅仅是把a和b中的值传递过去
	printf("调用后:%d %d", a, b);//10 20
	return 0;
}
void swap(int num1, int num2){//仅仅交换的是num1和num2里面记录的值
	int temp = num1;
	num1 = num2;
	num2 = temp;
}
#include <stdio.h>
void swap(int* p1, int* p2);
int main() {
	// 1.定义两个变量
	int a = 10;
	int b = 20;
	// 2.调用swap函数
	printf("调用前:%d %d\n",a,b);//10 20
	swap(&a,&b);//把a和b中的地址传递过去
	printf("调用后:%d %d", a, b);//20 10
	return 0;
}
void swap(int* p1, int* p2){//此时交换的是p1指向的变量和p2指向的变量的值
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}

细节

在这里插入图片描述
在这里插入图片描述

  • 还有输出(输出10)的原因

printf("%d\n", *p);前没有执行其他的代码,内存还没来得及回收

#include <stdio.h>
int* method();
int main() {
	// 调用method函数,并使用该函数中的变量a
	int*p = method();
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("%d\n", *p);// 不能打印的,因为method函数结束之后,该函数里面所有的变量也会随之消失
	return 0;
}

int* method() {
	int a = 10;
	return &a;
}

在这里插入图片描述

#include <stdio.h>
int* method();
int main() {
	// 调用method函数,并使用该函数中的变量a
	int*p = method();
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("拖点时间\n");
	printf("%d\n", *p);//10
}
int* method() {
	static int a = 10;//此时变量一直保存到程序结束
	return &a;
}

函数返回多个值

在这里插入图片描述

#include <stdio.h>
void getMaxAndMin(int arr[], int len, int* max, int* min);
int main() {
	// 1.定义数组
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int len = sizeof(arr) / sizeof(int);
	// 2.调用getMaxAndMin函数求最大值和最小值
	int max = arr[0];
	int min = arr[0];
	getMaxAndMin(arr, len, &max, &min);

	printf("数组的最大值为:%d\n", max);//10
	printf("数组的最小值为:%d\n", min);//1
	return 0;
}


void getMaxAndMin(int arr[], int len,int* max,int* min) {
	//求数组的最大值
	*max = arr[0];
	for (int i = 1; i < len; i++) {
		if (arr[i] > *max) {
			*max = arr[i];
		}
	}
	 
	//求数组的最小值
	*min = arr[0];
	for (int i = 1; i < len; i++) {
		if (arr[i] < *min) {
			*min = arr[i];
		}
	}
}

函数的结果和计算状态分开

在这里插入图片描述

#include <stdio.h>
int getRemainder(int num1, int num2, int* res);
int main() {
	// 1.定义两个变量
	int a = 10;
	int b = 3;
	int res = 0;
	int flag = getRemainder(a, b, &res);
	if (!flag) {
		printf("获取到的余数是:%d\n", res);//1
	}

	return 0;
}

//返回值:表示计算的状态 0为正常 1为不正常
//区分函数的结果和函数的运行状态
int getRemainder(int num1, int num2, int* res) {
	if (num2 == 0) {
		return 1;
	}
	*res = num1 % num2;
	return 0;
}

指针高级

在这里插入图片描述
在这里插入图片描述

指针的计算

在这里插入图片描述

指针的加减

#include <stdio.h>
int main() {
	 /*
		指针运尊:
			步长:指针移动一次,走了多少个字节
			char: 1
			short: 2
			int: 4
			long: 4
			long long: 8
			
			加法:指针往后移动了N步 p + N
			减法:指针往前移动了N步 p - N
	 */

	// 定义变量
	int a = 10;
	int* p = &a;
	printf("%p\n", p);      //00000077BFEFF884
	printf("%p\n", p + 1);  //00000077BFEFF888
	printf("%p\n", p + 2);  //00000077BFEFF88C

	printf("%p\n", p);      //000000D4594FF524
	printf("%p\n", p - 1);  //000000D4594FF520
	printf("%p\n", p - 2);  //000000D4594FF51C
	return 0;
}
总结

在这里插入图片描述

指针的操作

在这里插入图片描述

#include <stdio.h>
int main() {
	// 指针跟整数进行加、减操作(每次移动一个步长)
	// 前提条件:保证内存空间是连续的
	// 数组
	int arr[] = {1,2,3,4,5,6,7,8,9,10 };
	// 获取0索引的内存地址
	int* p1 = &arr[0];
	// 通过内存地址(指针p)获取数据
	printf("%d\n", *p1);//1
	printf("%d\n", *(p1 + 1));//2

	// 指针跟指针进行减操作(间隔步长)
	// 获取5索引的内存地址
	int* p2 = &arr[5];
	// p2 - p1 间隔了多少步长
	printf("%d\n", p2 - p1); //5
	//间隔了 5 * 4 = 20 个字节
	printf("%p\n", p1);      //0000000D4676F7C8
	printf("%p\n", p2);      //0000000D4676F7DC
 	return 0;
} 

指向不明的指针

在这里插入图片描述

野指针

#include <stdio.h>
int main() {
	// 野指针:指针指向的空间未分配
	int a = 10;
	int* p1 = &a;
	printf("%p\n", p1);   //000000893EFEF9D4
	printf("%d\n", *p1);  //10

	//p2为野指针
	int* p2 = p1 + 10;
	printf("%p\n", p2);   //000000893EFEF9FC
	printf("%d\n", *p2);  //137 有可能是其他程序的数据,不能随便改
 	return 0;
}

悬空指针

#include <stdio.h>
int* method();
int main() {
	// 悬空指针:指针指向的空间已分配,但是被释放了
	int* p2 = method();

	printf("拖点时间\n");

	printf("%p\n", p2);   //00000040E60FF9C4
	printf("%d\n", *p2);  //-858993460 已释放,不是原来的数据
 	return 0;
}

int* method() {
	int num = 10;
	int* p = &num;
	return p;
}

没有类型的指针

在这里插入图片描述

#include <stdio.h>
int main() {
	// 1。 定义两个变量
	int a = 10;
	short b = 20;
	// 2. 定义两个指针
	int* p1 = &a;
	short* p2 = &b;
	// 3. 输出打印
	printf("%d\n", *p1);//10
	printf("%d\n", *p2);//20
	
	// 不同类型的指针之间,是不能互相赋值的
	//char* p3 = p1;报错
	
	// void类型的指针打破上面的观念
	// void没有任何类型,好处可以接受任意类型指针记录的内存地址
	void* p3 = p1;
	void* p4 = p2;
	 
	// 缺点:void类型的指针,无法获取变量里面的数据,也不能进行加、减的计算
	//printf("%d\n",*p3);报错
	//printf("%p\n",p3 + 1);报错
 	return 0;
}
#include <stdio.h>
void swap(void* p1, void* p2, int len);
int main() {
	//调用函数交换数据
	int c = 100; 
	int d = 200;
	swap(&c, &d, 4);
	printf("c = %d,d = %d", c, d);
	return 0;
}

// 函数:用来交换两个变量记录的数据
// 修改一下函数,更具有通用性
void swap(void* p1, void* p2, int len) {
	// 把void类型的指针,转成char类型的指针
	char* pc1 = p1;
	char* pc2 = p2;
	char temp = 0;

	// 以字节为单位,一个字节一个字节的进行交换
	for (int i = 0; i < len; i++) {
		temp = *pc1; 
		*pc1 = *pc2;
		*pc2 = temp;
		pc1++;
		pc2++;
	}
}

二级指针和多级指针

在这里插入图片描述

#include <stdio.h>
int main() {
	/*
		二级指针
			格式:数据类型** 指针名
	*/
	//定义变量
	int a = 10;
	int b = 20;
	//定义一级指针
	int* p = &a;
	//定义二级指针
	int** pp = &p;

	//作用一:利用二级指针修改一级指针里面记录的内存地址
	*pp = &b;

	//输出打印
	printf("%p\n",&a);  //0000001749B5F664
	printf("%p\n",&b);  //0000001749B5F684
	printf("%p\n",p);   //0000001749B5F684

	// 作用二:利用二级指针获取到变量中记录的数据
	// *pp  获取到一级指针所记录的地址
	// **pp 通过一级指针所记录的地址,再去获取到变量里的数据
	printf("%d\n", **pp);//20
	return 0;
}

数组指针

在这里插入图片描述

#include <stdio.h>
int main() {
	/*
		练习:利用指针遍历数组
	*/

	// 1.定义数组
	int arr[] = {10,20,30,40,50}; 
	int len = sizeof(arr) / sizeof(int);
	// 2.获取数组的指针
	// 实际上获取的:数组的首地址
	int* p1 = arr;
	int* p2 = &arr[0];
	
	printf("%p\n", p1); //0000000FAE59F9E8
	printf("%p\n", p2); //0000000FAE59F9E8

	//3.利用循环和指针追历数组获取里面的每一个元素
	for (int i = 0; i < len; i++) {
		printf("%d\n", *p1++);
	}
	return 0;
}

细节

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
int main() {
	// 1.定义数组
	int arr[] = {1,2,3,4,5,6,7,8,9,10};

	// 2.sizeof 运自的时候,不会退化,arr还是整体
	printf("%zu\n",sizeof(arr));//40
	// 3.&arr 获取地址的时候,不会退化,记录的内存地址第一个元素的首地址,也是数组的首地址,步长:数据类型*数组的长度 40
	//   arr  参与计算的时候,会退化为第一个元素的指针,记录的内存地址第一个元素的首地址,也是数组的首地址,步长:数据类型 int 4
	printf("%p\n",arr);   //0000000B9256F948
	printf("%p\n",&arr);  //0000000B9256F948

	printf("%p\n",arr + 1); //步长:4
	printf("%p\n",&arr + 1);//步长:40
	return 0;
}

总结

在这里插入图片描述

二维数组

在这里插入图片描述

定义格式

在这里插入图片描述
在这里插入图片描述

索引操作

#include <stdio.h>
int main() {
	/*
		二维数组
			定义格式和遍历方式

			定义格式方式一:
				m:表示二维数组的长度
				n:表示每一个-维数组的长度
				数据类型 arr[m][n]=
				{
					{1,2,3,4,5....},
					{1,2,3,4,5....},
					{1,2,3,4,5....}
				};
			遍历:利用索引进行遍历 / 利用指针进行遍历
	*/

	// 1.定义一个二维数组
	int arr[3][5] =
	{
		{1, 2, 3, 4, 5},
		{11, 22, 33, 44, 55},
		{111,222,333,444,555}
	};

	// 2.利用索引的方式进行遍历
	// arr[0]:表示二维数组当中的第一个一维数组,{1,2,3,4,5}
	// arr[1]:表示二维数组当中的第二个一维数组,{11,22,33,44,55}
	// arr[2]:表示二维数组当中的第三个一维数组,{111,222,333,444,555}

	for (int i = 0; i < 3; i++) {
		// i:依次表示二维数组中的索引
		for (int j = 0; j < 5; j++) {
			// j:依次表示一维数组中的索引
			// 内循环:遍历每一个一维数组
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}

	return 0;
}

#include <stdio.h>
int main() {
	/*
		二维数组的定义格式二 + 索引遍历
			核心:事先先把所有的一维数组定义完毕,再放入到二维数组当中
	*/

	// 1.定义三个一维数组
	int arr1[3] = {1,2,3}; 
	int arr2[5] = {1, 2, 3, 4, 5}; 
	int arr3[9] = {1,2,3,4,5,6,7,8,9};

	//预先计算每一个数组真实的长度
	int len1 = sizeof(arr1) / sizeof(int); 
	int len2 = sizeof(arr2) / sizeof(int);
	int len3 = sizeof(arr3) / sizeof(int);

	// 再定义一个数组,装所有数组的长度
	int lenArr[3] = {len1, len2, len3};

	// 2.把三个一维数组放入到二维数组当中、
	// 数组的数据类型,跟内部存储的元素类型保持一致
	// arr1:使用数组名进行计算的时候,退化为指向第一个元素的指针,此时不再表示数组的那个整体了
	// 指针---内存地址 在64位win中 8个字节
	int* arr[3] = {arr1,arr2,arr3};//arr存储的是一维数组的地址

	// 3.利用索引遍历arr
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < lenArr[i]; j++) {
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}

	return 0;
}

指针操作

在这里插入图片描述

#include <stdio.h>
int main() {
	/*
		二维数组
			利用指针遍历二维数组
	*/
	
	// 1.定义一个二维数组
	int arr[3][5] =
	{
		{1,2,3,4,5},
		{11, 22, 33, 44, 55},
		{111,222,333,444,555}
	};

	// 2.利用指针遍历二维数组
	// 获取二维数组的指针

	// 数组指针的数据类型:要跟数组内部元素的类型保持一致
	// 二维数组里面存储的是一维数组
	int(*p)[5]= arr;
	// 相差20个字节
	printf("%p\n",arr);       //000000943A2FF808
	printf("%p\n", arr + 1);  //000000943A2FF81C

	for (int i = 0; i < 3; i++) {
		// 遍历一维数组
		for (int j = 0; j < 5; j++) {
			printf("%d ", *(*p + j));
		}
		// 换行
		printf("\n");

		//移动二维数组的指针,继续遍历下一个一维数组
		p++;
	}

	return 0;
}

在这里插入图片描述

#include <stdio.h>
int main() {
	/*
		二维数组
			利用指针遍历二维数组
	*/

	// 1.定义三个一维数组
	int arr1[5] = {1,2,3,4,5}; 
	int arr2[5] = {11,22,33,44,55}; 
	int arr3[5] = {111,2222,333,444,555};

	// 2. 把三个一维数组的内存地址,再放入到二维数组中
	int* arr[3] = {arr1,arr2,arr3};

	// 3.获取指针
	int** p = arr;

	// 4. 遍历数组
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 5; j++) {
			printf("%d ", *(*p + j));
		}
		// 换行
		printf("\n");

		//移动二维数组的指针,继续遍历下一个一维数组
		p++;
	}

	return 0;
}

数组指针和指针数组

在这里插入图片描述

函数指针

在这里插入图片描述

#include <stdio.h>
void method1();
int method2(int num1, int num2);
int main() {
	/*
		函数指针
	*/

	// 1. 定义指针指向两个函数
	void (*p1)() = method1;
	int (*p2)(int num1, int num2) = method2;

	// 2.利用函数指针去调用函数
	p1();
	int num = p2(10, 20);
	printf("%d\n", num);
	return 0;
}

void method1() {
	printf("method1\n");
}

int method2(int num1, int num2) {
	printf("method2\n");
	return num1 + num2;
}

练习

在这里插入图片描述

#include <stdio.h>
int add(int num1, int num2); 
int subtract(int num1, int num2);
int mutiply(int numl, int num2);
int divide(int numl, int num2);
int main() {
	// 1.定义一个数组去装四个函数的指针
	// 函数指针数组
	// 细节:只有形参完全相同而且返回值也要一样的函数,才能放到同公个函数指针数组当中
	int(*arr[4])(int,int) = {add,subtract,mutiply,divide};

	// 2.用户键盘录入三个数据
	printf("请录入两个数字参与计算\n");
	int num1;
	int num2;
	scanf("%d%d", &num1, &num2);

	int choose; 
	printf("请录入一个数字表示要进行的计算\n"); 
	scanf("%d", &choose);

	// 3.根据用户的选择,来调用不同的函数
	int res = (arr[choose -1])(num1,num2);

	// 4.输出打印
	printf("%d\n", res);

	return 0;
}

int add(int num1, int num2) {
	return num1 + num2;
}

int subtract(int num1, int num2) {
	return num1 - num2;
}

int mutiply(int num1, int num2) {
	return num1 * num2;
}

int divide(int num1, int num2) {
	return num1 / num2;
}
  • 18
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值