分享

UC头条:c语言分层理解(c语言指针(下))

 cnzrp 2023-05-28 发布于山西

1.指针数组和数组指针区分

指针数组是存放指针的数组,实质上是数组。数组指针是指向数组的指针,实质上是指针。

1.1指针数组

比如int*arr[10];这里怎么理解,这里的arr[10]就是数组,数组中存放的是int类型的指针。

用例子来说:

#includeintmain{char*arr[3]={'zhangsan','lisi','wangwu'};inti=0;for(i=0;i<3;i++){printf('%s\n',arr[i]);}return0;}

#includeintmain{intarr1[5]={1,2,3,4,5};intarr2[5]={2,3,4,5,6};intarr3[5]={3,4,5,6,7};int*arr[3]={arr1,arr2,arr3};inti=0;intj=0;for(i=0;i<3;i++){for(j=0;j<5;j++){printf('%d',arr[i][j]);}printf('\n');}return0;}

1.2数组指针

比如int(*arr)[10];这里的意思是arr是个指针,这个指针指向一个数组,数组中有十个元素,每个元素都是int类型。这里可以借用int*arr;类比,这里的意思是指向整型的指针变量arr。

这里需要注意的是&arr和arr,认识到这个数组指针,这里对其再次解读。

点击加载图片

这里的&arr的类型是int(*)[10];是一个数组指针类型,其他的是整型指针类型,所以&arr+1跳过的是整个数组。

打印一维数组元素:

#includevoidprint(int(*p)[10],intsz){inti=0;for(i=0;i

打印二维数组:

#includevoidprint(int(*p)[5],intr,intc){inti=0;intj=0;for(i=0;i<>

再来看看这个是什么鬼?

int(*parr[10])[5];

这个是什么东西?

首先它可拆分为两个int(*)[5]和parr[10],这里的意思是parr是存放数组指针的数组

2.数组参数和指针参数

2.1一维数组传参

intarr[10]={0};

可以用intarr[]和intarr[10]和int*arr接收。

int*arr[10]={0};

这里的arr可以用int*arr[10]和int**arr接收。

2.2二维数组传参

intarr[3][5]={0};

这里的arr可以用intarr[3][5]和intarr[][5]和int(*arr)[5]接收,其他的都不行。

2.3一级指针传参

voidtest(int*p){}

2.4二级指针传参

voidtest(int**ptr){}

这里的int**ptr可以用二级指针和&一级指针和指针数组传参。

3.函数指针

点击加载图片

这里的函数名就是函数的地址

这里用这个Add来写一下函数指针,void(*padd)(intx,inty);这个就是函数指针,首先把padd和void(*)(intx,inty)分开,首先是一个指针,这个指针的类型是函数,指向函数,这个函数的参数是x和y,返回值是void。

上述代码改进

intAdd(intx,inty){returnx+y;}intmain{inta=10;intb=20;int(*padd)(intx,inty)=&Add;intret=padd(3,5);printf('%d\n',ret);return0;}//结果是8

下面来看看这个代码是什么意思?

(*(void(*)())0)();

解释:void(*)()是函数指针类型,把0强制类型转换为函数指针类型,调用0地址处的函数。这里这个代码也可以写成(void(*)())0();

void(*signal(int,void(*)(int))(int);

解释:上述代码是函数声明,声明的函数叫做signal,函数的第一个参数是int类型,第二个参数是函数指针类型,该函数指针指向的函数参数是int,返回类型是void,signal函数的返回类型也是一个函数指针,该函数指针指向的函数参数是int,返回类型是void。

4.函数指针数组

比如:int(*p[3])(intx,inty);这里p是指数组,p中存放的是函数指针。

#includeintadd(inta,intb){returna+b;}intsub(inta,intb){returna-b;}intmul(inta,intb){returna*b;}intdiv(inta,intb){returna/b;}intmain{intx,y;intinput=1;intret=0;//函数指针数组int(*p[5])(intx,inty)={0,add,sub,mul,div};while(input){printf('*************************\n');printf('1:add2:sub\n');printf('3:mul4:div\n');printf('*************************\n');printf('请选择:');scanf('%d',&input);if((input<=4&&input>=1)){printf('输入操作数:');scanf('%d%d',&x,&y);ret=(*p[input])(x,y);//ret=p[input](x,y);}elseprintf('输入有误\n');printf('ret=%d\n',ret);}return0;}

5.指向函数指针数组的指针

函数指针数组:int(*p[3])(intx,inty);

指向函数指针数组的指针:int(*(*p)[3])(intx,inty);

6.回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

上述模拟计算器可以这样来写(利用回调函数):

#includeintAdd(intx,inty){returnx+y;}intSub(intx,inty){returnx-y;}intMul(intx,inty){returnx*y;}intDiv(intx,inty){returnx/y;}voidmenu{printf('***************************\n');printf('*****1.add2.sub****\n');printf('*****3.mul4.div****\n');printf('*****0.exit****\n');printf('***************************\n');}voidcalc(int(*p)(int,int)){intx=0;inty=0;intret=0;printf('请输入2个操作数:>');scanf('%d%d',&x,&y);//回调函数ret=p(x,y);printf('%d\n',ret);}intmain{intinput=0;do{menu;printf('请选择:>');scanf('%d',&input);switch(input){case1:calc(Add);break;case2:calc(Sub);break;case3:calc(Mul);break;case4:calc(Div);break;case0:printf('退出计算器\n');break;default:printf('选择错误\n');break;}}while(input);}

6.1.qsort库函数

初步了解:

点击加载图片

再次理解:

qsort库函数可以对任意类型数据进行排序,其原理类似于快速排序。

base:待排序数组的起始地址

num:待排序数据的元素个数

size:待排序数组的元素的大小

int(*compare)(constvoid*,constvoid*):比较两个元素的大小的函数指针

6.1.1qsort库函数排序整型数组

intcompare(constvoid*a,constvoid*b){return*(int*)a-*(int*)b;}voidprint(intarr[],intsz){inti=0;for(i=0;i

6.1.2qsort库函数排序结构体数据

6.1.2.1按照名字大小来排序

structstu{charname[20];intage;};intcmp_by_name(constvoid*a,constvoid*b){returnstrcmp(((structstu*)a)->name,((structstu*)b)->name);}voidprint(structstus[],intsz){inti=0;for(i=0;i

6.1.2.2按照年龄来排序

structstu{charname[20];intage;};intcmp_by_age(constvoid*a,constvoid*b){return(((structstu*)a)->age-((structstu*)b)->age);}voidprint(structstus[],intsz){inti=0;for(i=0;i

6.2实现冒泡排序对任意类型的排序

6.2.1对整型排序

intcmp_int(constvoid*e1,constvoid*e2){return(*(int*)e1-*(int*)e2);}voidSwap(char*buf1,char*buf2,intsize){inti=0;for(i=0;i<><>0){//交换Swap((char*)base+j*size,(char*)base+(j+1)*size,size);}}}}voidprint(intarr[],intsz){inti=0;for(i=0;i<>

6.2.2对结构体排序

6.2.2.1按照年龄进行排序

structstu{charname[20];intage;};intcmp_by_age(constvoid*a,constvoid*b){return(((structstu*)a)->age-((structstu*)b)->age);}voidSwap(char*buf1,char*buf2,intsize){inti=0;for(i=0;i<><>0){//交换Swap((char*)base+j*size,(char*)base+(j+1)*size,size);}}}}voidprint(structstus[],intsz){inti=0;for(i=0;i<>

6.2.2.2按照名字排序

structstu{charname[20];intage;};intcmp_by_name(constvoid*a,constvoid*b){returnstrcmp(((structstu*)a)->name,((structstu*)b)->name);}voidSwap(char*buf1,char*buf2,intsize){inti=0;for(i=0;i<><>0){//交换Swap((char*)base+j*size,(char*)base+(j+1)*size,size);}}}}voidprint(structstus[],intsz){inti=0;for(i=0;i<>

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多