广东网站设计,程序员免费自学网站,东莞视频课程网站建设,永川网站建设熊掌号一.字符指针 1.一般应用
#xff08;1#xff09;%c的应用 #xff08;2#xff09;%s的应用 字符指针没有权限通过解引用去改变指针指向的值 2.笔试题 题目#xff1a;判断输出结果 int main() { const char* p1 abcdef; const char* p2 …一.字符指针 1.一般应用
1%c的应用 2%s的应用 字符指针没有权限通过解引用去改变指针指向的值 2.笔试题 题目判断输出结果 int main() { const char* p1 abcdef; const char* p2 abcdef; char arr1[] abcdef; char arr2[] abcdef; if (p1 p2) { printf(p1p2\n); } else { printf(p1!p2\n); } if (arr1 arr2) { printf(arr1arr2\n); } else { printf(arr1!arr2\n); } return 0; } 解析 #includestdio.h int main() { const char* p1 abcdef; const char* p2 abcdef;//常量字符串zbcdef被存储在只读区,指针p1、p2存储了这个字符串的首元素地址 char arr1[] abcdef; char arr2[] abcdef;//数组arr1、arr2各开辟了一块内存空间将字符串zbcdef存储在开辟的内存中 if (p1 p2) { printf(p1p2\n); } else { printf(p1!p2\n); }//因为p1和p2都是字符串abcdef的地址是相同的 if (arr1 arr2) { printf(arr1arr2\n); } else { printf(arr1!arr2\n); }//arr1和arr2为各自开辟的内存空间中字符串abcdef首元素的地址 //两个内存空间不同所以这两个地址是不同的 return 0; } 二.指针数组——元素为指针的数组
1.指针数组的类型 2.指针数组的应用 三.数组指针——指向数组的指针
1.数组指针的定义 2.数组指针与指针数组的区别 #includestdio.h int main() { //数组的创建 int arr1[5] {1,2,3,4,5}; int arr2[5] {2,3,4,5,6}; int arr3[5] {3,4,5,6,7}; //指针数组 //parr是一个空间为3的数组其中存储的元素为int*类型的 //parr的类型为int*[3] int* parr[3] {arr1,arr2,arr3}; //数组指针 //p为一个指针其指向的元素为int[5]类型的 //为了体现p是一个指针故将*与p用()圈起来 //p的类型为int(*)[5] int(*p)[5] arr1; int(*p)[5] arr2; int(*p)[5] arr3;//—————————————————————————————————————————————————— //练习 int* (*pp)[3] parr; //pp为一个指针其指向的元素为int*[3]类型的 //为了体现pp是一个指针故将*与pp用()圈起来 //p的类型为int*(*)[3] return 0; } 3.数组名的相关应用 4.数组指针的应用
例题 #includestdio.h void printf1(int arr[3][5],int h,int l) //*(*(arrH)L)arr[H][L],故用数组传参和指针传参本质相同 { int H,L; for (H 0; H h; H) { for (L 0; L l; L) { printf(%d ,arr[H][L]); } printf(\n); } } void printf2(int(*p)[5],int h,int l) //二重指针首元素的地址为第一行元素 { int H,L; for (H 0; H h; H) { for (L 0; L l; L) { printf(%d ,*(*(pH)L)); //printf(%d ,p[H][L]); 相同 } printf(\n); } }//若设arr数组的第一行元素为一维数组brr数组指针p解引用后为整个数组brrbrr为数组名相当于首元素地址。 //所以数组指针p解引用后为brr的首个元素故*(pH)会依次获取每一行一维数组的首元素地址 //*(pH)L会依次获取每一行中的每一个元素的地址,故*(*(pH)L)会获取每一行中的每一个元素 int main() { int arr[3][5] {1,2,3,4,5,2,3,4,5,6,3,4,5,6,7}; int h 3; //行 int l 5; //列 //数组传参输出 printf1(arr,h,l); printf(\n); //指针传参输出 printf2(arr,h,l); return 0; } 输出结果 5.存放数组指针的数组 #includestdio.h int main() { int arr1[] {1,2,3,4}; int arr2[] {2,3,4,5}; int arr3[] {3,4,5,6}; int(*p1)[4] arr1; int(*p2)[4] arr2; int(*p3)[4] arr3; //数组指针不能没有元素个数定义数组的时候可以没有 int(*p[3])[4] {arr1,arr2,arr3}; //存放数组指针的数组其中元素指向的元素类型为int[4] //其类型为int(*[3])[4] return 0; } 四.数组传参和指针传参
1.一维数组传参 #includestdio.h void test1(int arr1[]) {} void test1(int arr1[10]) //形参数组的元素可有可无 {} void test1(int* arr1) //接收首元素地址 {} void test2(int* arr2[]) {} void test2(int* arr2[20]) //形参数组的元素可有可无 {} void test2(int** arr2) //接收首元素地址 {} int main() { int arr1[10] {0}; int* arr2[20] {0}; test1(arr1); test2(arr2); return 0; } 2.二维数组传参 #includestdio.h void test(int arr[][5]) //二维数组的行可以省略列不能省略 {} void test(int arr[3][5]) {} void test(int(*arr)[5]) //接收首元素地址--一个一维数组的地址 {} int main() { int arr[3][5] {0}; test(arr); return 0; } 3、一级指针传参 #includestdio.h void print(int* p) //若实参的本质是一个一级整形指针就可以传参 {} int main() { int a 10; int* ptr a; int arr[10]; print(a); print(ptr); print(arr); return 0; } 4.二级指针传参 #includestdio.h void test(int** p) //若实参的本质是一个二级整形指针就可以传参 {} int main() { int* p1; int** p2; int* arr[10]; //指针数组 test(p1); test(p2); test(arr); return 0; } 五.函数指针
1.函数指针的定义 #includestdio.h int Add(int x, int y) { return x y; } int main() { printf(%p\n,Add); //00007FF6991B13E8 printf(%p\n,Add); //00007FF6991B13E8 //函数名—取出的是函数的地址 //对于函数来说函数名和函数名都是函数的地址 int (*p)(int, int) Add; //int p (int,int) Add; int ret (*p)(2, 3); //int ret p (2,3); //对p解引用后得到函数Add故(*p)(2, 3)Add(2,3) printf(%d ,ret); return 0; } 2.函数指针的应用 #includestdio.h int Add(int x, int y) { return x y; } void calc(int(*p)(int, int)) { int a 3; int b 5; int ret p(a, b); printf(%d\n,ret); } int main() { calc(Add); //将函数Add传递给函数calc使其在函数内用指针调用Add函数 return 0; } 3.特殊的用法——来自《c的陷阱与缺陷》
(1)例一 int main() { //求解如下代码的含义 (*(void(*)())0)(); // void(*)() 返回值为void类型无参的函数指针 // ( )0 将0强制类型转换为函数指针类型 //(* )() 将函数指针类型的0解引用调用指向地址为0处的函数 //综上可知这段代码的含义为一次函数调用 return 0; } 2例二 int main() { //求解如下代码的含义 void(*signal(int,void(*)(int)))(int);// signal(int,void(*)(int)) 接收以整形和数组指针为参数的函数的函数指针 // void(* )(int) 解引用得到函数signal // 最后得到void signal (int)——为一次函数声明 return 0; } 4.函数指针的应用 #includestdio.h //简易计算器 void menu() { //add—加 sub—减 mul—乘 div—除 printf(*********************************************\n); printf(********* 1.add 2.sub ***********\n); printf(********* 3.mul 4.div ***********\n); printf(********* 0.exit ***********\n); printf(*********************************************\n); } int add(int x, int y) { return x y; } int sub(int x, int y) { return x - y; } int mul(int x, int y) { return x * y; } int div(int x, int y) { return x / y; } void DiaoYong(int (*p)(int,int)) //使用函数指针 减少代码冗余度 { int x 0; int y 0; printf(请输入两个整数\n); scanf(%d %d,x,y); int np(x,y); printf(%d\n,n); } int main() { int input 0; do { menu(); printf(请输入选项\n); scanf(%d,input); switch (input) { case 1: DiaoYong(add); break; case 2: DiaoYong(sub); break; case 3: DiaoYong(mul); break; case 4: DiaoYong(div); break; case 0: printf(退出程序\n); break; default: printf(数值错误请重新输入\n); break; } } while (input); return 0; } 5.typedef对函数指针的用法 #includestdio.h typedef void(*pt)(int);//将void(*)(int)改名为pt int main() { void(*signal(int,void(*)(int)))(int); void(*signal(int, pt))(int); return 0; } 六.函数指针数组
1.函数指针的形式 #includestdio.h //输出两个整数加减乘除的结果 int add(int x, int y) { return x y; } int sub(int x, int y) { return x - y; } int mul(int x, int y) { return x * y; } int div(int x, int y) { return x / y; } int main() { int input 0; // int(*p)(int, int) add; //函数指针 int(*p[4])(int, int) {add,sub,mul,div}; //函数指针数组 for (int i0;i4;i) { printf(%d\n,p[i](8,4)); } return 0; } 2.函数指针的应用 #includestdio.h //简易计算器 void menu() { //add—加 sub—减 mul—乘 div—除 printf(*********************************************\n); printf(********* 1.add 2.sub ***********\n); printf(********* 3.mul 4.div ***********\n); printf(********* 0.exit ***********\n); printf(*********************************************\n); } int add(int x, int y) { return x y; } int sub(int x, int y) { return x - y; } int mul(int x, int y) { return x * y; } int div(int x, int y) { return x / y; } int main() { int input 0; int x 0; int y 0; int ret 0; int (*p[5])(int, int) {0,add,sub,mul,div}; do { menu(); printf(请输入选项\n); scanf(%d, input); if (input 0) { printf(退出计算器\n); } else if(input 1 input 4) { printf(请输入两个整数\n); scanf(%d %d, x,y); printf(%d\n, p[input](x,y)); } }while (input); return 0; } 七.指向函数指针数组的指针 int main() { //函数指针数组 int (*p[5])(int, int) {0,add,sub,mul,div}; //指向[函数指针数组]的指针 int(*(*pr)[5])(int, int) p; return 0; } 八.回调函数 1.回调函数的定义
2. 回调函数的应用
1例一简易计算器 #includestdio.h //简易计算器 void menu() { //add—加 sub—减 mul—乘 div—除 printf(*********************************************\n); printf(********* 1.add 2.sub ***********\n); printf(********* 3.mul 4.div ***********\n); printf(********* 0.exit ***********\n); printf(*********************************************\n); } int add(int x, int y) { return x y; } int sub(int x, int y) { return x - y; } int mul(int x, int y) { return x * y; } int div(int x, int y) { return x / y; }void DiaoYong(int (*p)(int,int)) //使用函数指针 减少代码冗余度——回调函数 { int x 0; int y 0; printf(请输入两个整数\n); scanf(%d %d,x,y); int np(x,y); printf(%d\n,n); } int main() { int input 0; do { menu(); printf(请输入选项\n); scanf(%d,input); switch (input) { case 1: DiaoYong(add); break; case 2: DiaoYong(sub); break; case 3: DiaoYong(mul); break; case 4: DiaoYong(div); break; case 0: printf(退出程序\n); break; default: printf(数值错误请重新输入\n); break; } } while (input); return 0; } 2例二 qsort()函数的应用——整数排序 #includestdio.h #includestdlib.h//void qsort qsort()函数初始是递增排序 // (void* base, 要排序的初始位置 // size_t num, 待排序的元素个数 // size_t width, 待排序的数据元素的大小字节 // int(*cmp)(const void* e1,const void* e2)) 函数指针—比较函数 //_cdecl——函数调用约定约定函数由c语言的语法调用 //设置比较函数 int cmp1(const void* x1, const void* x2) { return *(int*)x1 - *(int*)x2; } int cmp2(const void* x1, const void* x2) { return *(int*)x2 - *(int*)x1; }//函数定义要求e1-e20时输出整数e1-e20时输出10e1-e20时输出负数 //qsort()函数初始是递增排序若要变为递减排序则要交换e1和e2 int main() { //定义数组 int i 0; int arr[10] {9,8,7,6,5,4,3,2,1,0}; int brr[10] {0,1,2,3,4,5,6,7,8,9}; //求排序数组的大小 int sz1 sizeof(arr) / sizeof(arr[0]); int sz2 sizeof(brr) / sizeof(brr[0]); //调用qsort()函数 qsort(arr,sz1,sizeof(int),cmp1); qsort(brr,sz2,sizeof(int),cmp2); //输出排序后的数组 for (i 0; i sz1; i) { printf(%d ,arr[i]); } printf(\n); for (i 0; i sz2; i) { printf(%d , brr[i]); } return 0; } 3qsort()函数的应用——结构体排序 #includestdio.h #includestdlib.h #includestring.h//void qsort qsort()函数初始是递增排序 // (void* base, 要排序的初始位置 // size_t num, 待排序的元素个数 // size_t width, 待排序的数据元素的大小字节 // int(*cmp)(const void* e1,const void* e2)) 函数指针—比较函数 //_cdecl——函数调用约定约定函数由c语言的语法调用 //函数定义要求e1-e20时输出整数e1-e20时输出10e1-e20时输出负数//qsort()函数初始是递增排序若要变为递减排序则要交换e1和e2 struct Stu { char name[20]; int age; };//设置比较函数 int cmp1(const void* x1, const void* x2) { return strcmp(((struct Stu*)x1)-name,((struct Stu*)x2)-name); } int cmp2(const void* x1, const void* x2) { return ((struct Stu*)x1)-age - ((struct Stu*)x2)-age; } void test1() //排序结构体的name元素 { struct Stu s[3] { {zhangsan,15},{lisi,30},{wangwu,25} }; int sz sizeof(s) / sizeof(s[0]); qsort(s, sz, sizeof(s[0]),cmp1); for (int i 0; i 3; i) { printf(%s , s[i].name); } } void test2() //排序结构体的age元素 { struct Stu s[3] { {zhangsan,15},{lisi,30},{wangwu,25} }; int sz sizeof(s) / sizeof(s[0]); qsort(s, sz, sizeof(s[0]), cmp2); for (int i 0; i 3; i) { printf(%d , s[i].age); } } int main() { test1(); printf(\n); test2(); return 0; } 4用冒泡排序模拟实现qsort()函数 #includestdio.h int cmp(const void* x1, const void* x2) { return (*(int*)x1 - *(int*)x2); } void Swap(char* x, char* y, int width) //将两个数改为char*类型每次只交换一个字节,直到将int*的四个字节全部交换一遍 { int i 0; for (i 0; i width; i) { char tmp *x; *x *y; *y tmp; x; y; } } sqort_moni(int* arr,int sz,int width, int (*cmp)(const void*, const void*)) { int i,j; for (i 0; i sz - 1; i) { int flag 1; for (j 0; j sz - 1 - i; j) { if (cmp((char*)arr j * width, (char*)arr (j 1) * width ) 0) //返回值大于0则说明x1x2,需要顺序排列则要交换两个数 { Swap((char*)arr j * width, (char*)arr (j 1) * width, width); flag 0; } } if (flag 1) //如果循环一整遍之后都符合条件则直接跳出循环 { break; } } } int main() { int arr[10] {9,8,7,6,5,4,3,2,1,0}; int sz sizeof(arr) / sizeof(arr[0]); sqort_moni(arr,sz,sizeof(arr[0]), cmp); for (int i 0; i sz; i) { printf(%d ,arr[i]); } return 0; }