一、定义:
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语言很重要的一个知识点,希望我们一起学好它!有错误的欢迎指出!