*指针阶段学习总结

一、定义:

1.指针是一种用来存储另一个变量地址的变量。

2.它可以用来访问和操作内存中的数据,通过间接寻址的方式获取变量的值。

二、类型:

1.根据指针所指向数据类型,可分为整数指针(int*)、字符型指针(char*)、浮点型指针(float*)、结构指针(struct*)和联合指针(union*)。

2.还可以分为一级指针、二级指针、三级指针等,每增加一级指针,就相当于多了一层间接寻址。

三、初始化和赋值:

1.指针必须初始化为指向一个有效的内存地址,通常使用&运算符来获取变量的地址,并赋值给变量。

2.可以通过直接赋值的方式将一个已有的地址复制给指针变量,也可以通过函数返回值来获取地址并赋值给指针变量。

四、指针运算:

1.指针+-整数

#include<stdio.h>
int  main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = &arr[0];
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0;i < sz;i++)
	{
		printf("%d", *(p + i));
	}
	return 0;
}

2.指针-指针

#include <stdio.h>
int my_strlen(char* s)
{
	char* p = s;
	while (*p != '\0')
		p++;
	return p - s;
}
int main()
{
	printf("%d\n", my_strlen("abc"));
	return 0;
}

3.指针的运算关系


#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = &arr[0];
	int sz = sizeof(arr) / sizeof(arr[0]);
	while (p < arr + sz) 

	{
	 printf("%d ", *p);
	 p++;
	}
	return 0;
}

五、冒泡排序:

两两元素相互比较,第一个for循环表示比较组数,第二个for循环表示单个数字比较次数

#include<stdio.h>

void bubble_sort(int arr[100], 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[5] = { 0 };

	int sz = sizeof(arr) / sizeof(arr[0]);

	int i = 0;

	for (i = 0;i < sz;i++)

	{

		scanf("%d", &arr[i]);

	}

	bubble_sort(arr, sz);

	for (i = 0;i < sz;i++)

	{

		printf("%d", arr[i]);

	}

	return 0;

}

六、数组指针与指针数组:

1.指针数组是用来存放指针的数组(int*arr[10])。

2.数组指针是用来存放指针的数组(int(*arr)[10])。

七、一维数组传参与二维数组传参的本质:

1.当我们将一维数组作为参数传递给函数时,实际上是将数组名(即指向数组首元素的指针)传递给函数。因此,传递的是数组的首地址,而不是数组中的每个元素。这种传递方式无需复制数组内容,效率较高

void test(int arr[]) 
{

}

这里arr是一个指向一维数组首元素的指针。

2.二维数组在内存中的存储方式是按照行主序(或列主序,取决于具体的语言和编译器)进行的。因此,从内存的角度看,二维数组本质上是一个一维数组,只是每一行都被视为一个整体。当我们将二维数组作为参数传递时,通常有两种主要方法:

void fun(int arr[][N]) 
{
   }

这种方式传递的是整个二维数组的首地址,形参arr是一个指向二维数组首元素的指针。

 void fun(int (*arr)[N]) 
{
   }

这种方式传递的是指向二维数组首行的指针,形参arr是一个指向一维数组的指针。

void fun(int **arr, int rows, int cols) 
{

   }

这种方式传递的是指向二维数组首元素的二级指针,并且需要额外传递行数和列数以确保正确访问数组元素。 

八、函数指针:

存放函数地址,并且能通过函数地址来调用函数。

九、函数指针数组:

数组内的每一个元素类型都是函数指针,运用函数指针数组我们可以做简单计算器的实现。

#include<stdio.h>
void menu()
{
	printf("*************************************\n");
	printf("      1:add                    2:sub\n ");
	printf("      3:mul                    4:div\n ");
	printf("      0:exit                        \n ");
	printf("*************************************\n");
	printf("请选择: ");
}
int add(int a,int b)
{
	return a + b;
 }
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a * b;
}
int div(int a, int b)
{
	return a / b;
}//先写好我们所需的函数
int main()
{
	int x, y;
	int input=0 ,ret=0 ;
	int (*p[5])(int x, int y) = { 0,add,sub,mul,div };//数组的第一个下标是0,所以先写出0
	do
	{
		menu();
		scanf("%d",&input);//选择调用函数类型
		if ((input <= 4) && (input >= 1))
		{
			getchar();//去掉空格
			printf("请输入基操数: ");
			scanf("%d %d", &x, &y);
			ret = (*p[input])(x, y);对选择的数字进行计算
			printf("ret=%d\n", ret);
			break;
		}
		else if (input == 0)
		{
			printf("退出计算器\n");
			break;
		}
		else
		{
			printf("输入有误\n");//选择其他数字时显示
			break;
		}
	
	} 
		while (input);
	return 0;
}

十、回调函数:

1.定义:把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数,回调函数不是由该函数的实现方直接实现,而是在特定的事件或条件发生时由另外一方调用的。

由此我们可以举例qsort函数来演示

#include<stdio.h>
#include<string.h>
struct Stu
{
	char name[20];//名字
	int age;//年龄
};
int cmp_stu_by_age(const void*p1,const void*p2)//按年龄比
{
	return ((struct Stu*)p1)->age-((struct Stu*)p2)->age;

}
int cmp_stu_by_name(const void *p1, const void* p2)//按名字比
{
	return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);//strcmp函数专门用来比较字符串大小

}
void test2()//按名字来排序
{
	struct Stu s[] = { {"ZhangSan",20},{"LiSi",30},{"WanWu",15} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);}//qsost函数排序(内容,范围,类型,条件)不能调换顺序

void test3()//按年龄来排序
{

	struct Stu s[] = { {"ZhangSan",20},{"LiSi",30},{"WanWu",15} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}
int main()
{
	test2();
	test3();

	return 0;
}

十一、sizeof与strlen

1.sizeof是操作符,只关注占用内存大小,不关注内存中存放什么数据。

#include<stdio.h>
int main()
{
	int a = 10;
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof a);
	printf("%d\n", sizeof(int));
	return 0;
}

2.strlen是库函数,统计\0前的字符串长度,若无\0可能越界。

#include<stdio.h>
int main()
{
	char arr1[] = { 'a','b','c' };
	char arr2[] = "abc";
	printf("%d\n", strlen(arr1));//越界打印随机值
	printf("%d\n", strlen(arr2));
	printf("%d\n", sizeof(arr1));
	printf("%d\n", sizeof(arr2));//sizeof打印地址时为4/8
	return 0;
}

十二、完结撒花!

指针是C语言很重要的一个知识点,希望我们一起学好它!有错误的欢迎指出!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值