指针进阶(C语言)

指针进阶

头文件

#include<stdio.h> #include<stdlib.h> #include<string.h>

字符指针

int main() { //字符指针 char arr1[]="abcdef"; char arr2[]="abcdef"; char* p1="abcdef"; char* p2="abcdef"; if (arr1==arr2) { printf("hehe\n"); } else { printf("haha\n"); } if (p1==p2) { printf("hehe\n"); } else { printf("haha\n"); } printf("arr1:%p\n",arr1); printf("arr2:%p\n",arr2); printf("p1:%p\n",p1); printf("p2:%p\n",p2); return 0; }

指针数组

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[]={arr1,arr2,arr3};//指针数组-数组-存放指针的数组 int i = 0; for (i=0;i<3;i++) { int j=0; for (j=0;j<5;j++) { printf("%d ",*(parr[i]+j)); } printf("\n"); } return 0; }

数组指针

int main() { int arr[5]={1,2,3,4,5}; int (*p)[5]=&arr;//数组指针-指针-数组的地址要存起来 return 0; } int main() { char* arr[5]; char* (*p)[5]=&arr; return 0; } int main() { int arr[10]={1,2,3,4,5,6,7,8,9,10}; int *p=arr;//arr[i]==*(arr+i)==*(p+i)==p[i] int i=0; for(i=0;i<10;i++) { printf("%d ",*(p+i)); } // int (*p)[10]=&arr; // int i=0; // for(i=0;i<10;i++) // { // printf("%d ",(*p)[i]); // } // for(i=0;i<10;i++) // { // printf("%d ",*(*p+i));//*p==arr // } return 0; }

数组参数,指针参数

//参数是数组的形式 void print1(int arr[3][5],int x,int y) { int i=0; int j=0; for (i=0;i<x;i++) { for (j=0;j<y;j++) { printf("%d ",arr[i][j]); } printf("\n"); } } //参数是指针的形式 void print2(int(*p)[5],int x,int y) { int i=0; for(i=0;i<x;i++) { int j=0; for(j=0;j<y;j++) { //printf("%d ",p[i][j]); //printf("%d ",*(p[i]+j)); printf("%d ",*(*(p+i)+j)); //printf("%d ",(*(p+i))[j]); } printf("\n"); } }

二维数组传参

int main() { int arr[3][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}}; print1(arr,3,5);//arr-数组名-数组名就是首元素地址 print2(arr,3,5);// return 0; } void test(int arr[3][5]) {} void test1(int arr[][5])//可以省略行 {} // void test2(int arr[3][])//err 不可以省略列 // {} // void test3(int *arr)//err // {} // void test4(int **arr)//err // {} void test5(int (*arr)[5]) {} int main() { int arr[3][5]={0}; // test(arr);//二维数组传参 // test1(arr); // test2(arr); // test3(arr); // test4(arr); test5(arr); return 0; } void test1(int** p) {} int main() { int *ptr; test1(&ptr); int **pp=&ptr; test1(pp); int* arr[10]; test1(arr); return 0; }

函数指针

//数组指针——是指向数组的指针 //函数指针——是指向函数的指针——存放函数地址的指针 int Add(int x,int y) { int z=0; z=x+y; return z; } int main() { int a=10; int b=20; // int arr[10]={0}; // int (*p)[10]=&arr; //printf("%d\n",Add(a,b)); //&arr; //arr; //&函数名 和 函数名 都是函数的地址 /* printf("%p\n",&Add); printf("%p\n",Add); */ int (*pa)(int,int) = Add; printf("%d\n",(*pa)(2,3)); return 0; } void Print(char* str) { printf("%s\n",str); } int main() { void (*p)(char*) = Print; (*p)("hello bite"); return 0; } // 代码一 // (*(void(*)())0)(); // void(*)()-函数指针类型 // 把0强制类型转换成void(*)()函数指针类型-0就是一个函数地址 // 调用0地址处的该函数 // 代码二 // void (*singal(int ,void(*)(int)))(int); // signal是一个函数声明 // signal第一个参数整形,第二个参数是函数指针类型,该函数指针指向的函数的参数是int,返回类型是void // signal函数返回类型-函数指针-void(* singal(int,void(*)(int)) )(int) // 简化 // typedef void(*pfun_t)(int); // pfun_t signal(int,pfun_t); // typedef unsigned int unit; int Add(int x,int y) { int z=0; z=x+y; return z; } int main() { int a=10; int b=20; int (*pa)(int,int) = Add; printf("%d\n",pa(2,3)); printf("%d\n",Add(2,3)); printf("%d\n",(*pa)(2,3));//*是摆设 // printf("%d\n",(**pa)(2,3)); // printf("%d\n",(***pa)(2,3));没必要 return 0; }

函数指针数组

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* arr[5]; //需要一个数组可以存放四个函数的地址 - 函数指针的数组 //int (*pa)(int,int) = Add;//Sub/Mul/Div int (*parr[4])(int,int) = {Add,Sub,Mul,Div};//函数指针的数组 int i = 0; for (i=0;i<4;i++) { printf("%d\n",parr[i](2,3)); } return 0; }

函数指针数组的用途:转移表

void menu() { printf("*****************\n"); printf("** 1.add 2.sub**\n"); printf("** 3.mul 4.div**\n"); printf("** 5.Xor 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 Xor(int x,int y) { return x^y; } int main() { int input = 0; int x = 0; int y = 0; //转移表 int (*pfArr[])(int,int)={0,Add,Sub,Mul,Div,Xor}; do { menu(); printf("请选择:>"); scanf("%d",&input); if(input >= 1 && input <=5) { printf("请输入两个操作数:>"); scanf("%d%d",&x,&y); int ret = pfArr[input](x,y); printf("%d\n",ret); } else if(input == 0) { printf("退出\n"); } else { printf("选择错误\n"); } }while(input); return 0; }

回调函数

void Calc(int (*pf)(int,int)) { int x = 0; int y = 0; printf("请输入两个操作数:>"); scanf("%d%d",&x,&y); printf("%d\n",pf(x,y)); } int main() { int input = 0; do { menu(); printf("请选择:>"); scanf("%d",&input); switch (input) { case 1: Calc(Add); break; case 2: Calc(Sub); break; case 3: Calc(Mul); break; case 4: Calc(Div); break; case 0: printf("退出\n"); break; default: printf("选择错误\n"); break; } }while(input); return 0; } //回调函数2 void print(char* str) { printf("hehe:%s",str); } void test( void(*p)(char*) ) { printf("test\n"); p("bit"); } int main() { test(print); return 0; }

指向函数指针数组的指针

int Add(int x,int y) { return x+y; } int main() { int arr[10]={0}; int (*p)[10]=&arr;//取出数组的地址 int (*pfArr[4])(int,int);//pfArr是一个数组-函数指针数组 //ppfArr是一个指向[函数指针数组]的指针 int (*(*ppfArr)[4])(int,int) = &pfArr; // //ppfArr是一个数组指针,指针指向的数组有四个元素 //指向的数组的每个元素的类型是一个函数指针int(*)(int,int) // return 0; }

冒泡排序

void bubble_sort(int arr[],int sz) //整形的冒泡排序 { int i = 0; for (i=0;i<sz-1;i++) { int j=0; for (j=0;j<sz-1-i;j++) { if (arr[j]>arr[j+1]) { int tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp; } } } } // void qsort(void *base, size_t nmemb, size_t size, // int (*compar)(const void *a, const void *b)); //base:指向待排序数组的第一个元素的指针。 //nmemb:数组中元素的数量。sz //size:每个元素的大小(以字节为单位)。width //compar:用于比较两个元素的函数指针,比较两个元素的所用函数的地址-这个函数使用者自己实现函数指针的两个参数是:带比较的两个元素的地址。 int cmp_int(const void* a,const void* b) { //比较两个整形值 return (*(int*)a - *(int*)b);; } void test1() { int arr[10]={9,8,7,6,5,4,3,2,1,0}; int sz = sizeof(arr) / sizeof(arr[0]); qsort(arr,sz,sizeof(arr[0]),cmp_int); int i = 0; for (i=0;i<sz;i++) { printf("%d ",arr[i]); } } int cmp_float(const void*a,const void* b) { return *(float*)a - *(float*)b; } void test2() { float f[]={9.0,8.0,7.0,6.0,5.0,4.0,3.0}; int sz = sizeof(f) / sizeof(f[0]); qsort(f,sz,sizeof(f[0]),cmp_float); int j = 0; for (j=0;j<sz;j++) { printf("%f ",f[j]); } } struct Stu { char name[20]; int age; }; int cmp_stu_by_age(const void* a,const void* b) { return ((struct Stu*)a)->age - ((struct Stu*)b)->age; } int cmp_stu_by_name(const void* a,const void* b) { //比较字符串用strcmp return strcmp(((struct Stu*)a)->name,((struct Stu*)b)->name); } void test3() { struct Stu s[3]={{"zhangsan",20},{"lisi",30},{"wangwu",10}}; int sz = sizeof(s) / sizeof(s[0]); //qsort(s,sz,sizeof(s[0]),cmp_stu_by_age); qsort(s,sz,sizeof(s[0]),cmp_stu_by_name); int k = 0; for (k=0;k<sz;k++) { printf("%d " ,s[k].age); //printf("%s " ,s[k].name); } } // 实现bubble_sort函数的程序员,他是否知道未来排序的数据类型-不知道 // 那程序员也不知道,带比较的两个元素的类型 void Swap(char* buf1,char* buf2,int width) { int i = 0; for(i=0;i<width;i++) { char tmp = *buf1; *buf1 = *buf2; *buf2 = tmp; buf1++; buf2++; } } void bubble_sort(void* base,int sz,int width,int(*cmp)(void*a,void*b)) { int i = 0; //趟数 for (i=0;i<sz-1;i++) { //每一趟比较的对数 int j = 0; for(j=0;j<sz-1-i;j++) { //两个元素比较 if(cmp((char*)base+j*width,(char*)base+(j+1)*width)>0) { //交换 Swap((char*)base+j*width,(char*)base+(j+1)*width,width); } } } } void test4() { int arr[10]={9,8,7,6,5,4,3,2,1,0}; int sz = sizeof(arr) / sizeof(arr[0]); //使用bubble_sort的程序员一定知道自己排序的是什么数据、 //就应该知道如何比较待排序数组中的元素 bubble_sort(arr,sz,sizeof(arr[0]),cmp_int); int i = 0; for (i=0;i<sz;i++) { printf("%d ",arr[i]); } } void test5() { struct Stu s[3]={{"zhangsan",20},{"lisi",30},{"wangwu",10}}; int sz = sizeof(s) / sizeof(s[0]); bubble_sort(s,sz,sizeof(s[0]),cmp_stu_by_age); int k = 0; for (k=0;k<sz;k++) { printf("%d " ,s[k].age); //printf("%s " ,s[k].name); } } int main() { //test1(); //test2(); //test3(); //test4(); test5(); return 0; }

例题

int main() { //数组名是首元素的地址 //1.sizeof(数组名) - 数组名表示首元素地址 //2.&数组名 - 数组名表示整个数组 //一维数组 int a[] = {1,2,3,4};//4*4=16 printf("%d\n",sizeof(a));//16-sizeof(数组名)-计算的是数组总大小-单位是字节 printf("%d\n",sizeof(a+0));//数组名这里表示首元素地址,a+0还是首元素地址,地址大小就是4/8个字节 printf("%d\n",sizeof(*a));//4-数字名表示首元素地址,*a就是首元素,sizeof(*a)就是4 printf("%d\n",sizeof(a+1));//a+1第二个元素地址,地址大小为4/8 printf("%d\n",sizeof(a[1]));//4-第二个元素的大小 printf("%d\n",sizeof(&a));//&a取出的是数组的地址,数组的地址也是地址,地址大小为4/8 printf("%d\n",sizeof(*&a));//16 - &a是取数组的地址,数组的地址解引用访问的数组,sizeof计算的就是数组的大小单位是字节 printf("%d\n",sizeof(&a+1));//&a是数组的地址,&a+1虽然地址跳过整个数组,但还是地址,所以是4/8 printf("%d\n",sizeof(&a[0]));//&a[0]是第一个元素的地址 printf("%d\n",sizeof(&a[0]+1));//&a[0]+1是第二个元素的地址 //字符数组 char arr[] = {'a','b','c','d','e','f'}; printf("%d\n",sizeof(arr));//sizeof计算的是数组大小,6*1=6字节 printf("%d\n",sizeof(arr+0));//arr是首元素的地址,arr+0还是首元素的地址 地址的大小4/8 printf("%d\n",sizeof(*arr));//1 arr是首元素地址 *arr就是首元素 首元素是字符大小是一个字节 printf("%d\n",sizeof(arr[1]));//1 printf("%d\n",sizeof(&arr));//&arr 虽然是数组的地址,但还是地址,地址大小4/8 printf("%d\n",sizeof(&arr+1));//&arr+1 是跳过整个数组的地址,地址大小4/8 printf("%d\n",sizeof(&arr[0]+1));//第二个元素的地址,地址大小4/8 printf("%d\n",strlen(arr));//随机值1 printf("%d\n",strlen(arr+0));//随机值1 // printf("%d\n",strlen(*arr));//err // printf("%d\n",strlen(arr[1]));//err // printf("%d\n",strlen(&arr));//随机值1 // printf("%d\n",strlen(&arr+1));//随机值2 -6 // printf("%d\n",strlen(&arr[0]+1));//随机值3 -1 return 0; }

__EOF__

本文作者bumper
本文链接https://www.cnblogs.com/bumper/p/17605540.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   bumper  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示