新闻详情

新闻详情

首页 / 资讯中心 / 详情

C 语言指针从入门到避坑:把指针踩在脚底(4)

发布时间:2026/9/30 19:53:11来源:尧图网络
C 语言指针从入门到避坑:把指针踩在脚底(4)
目录字符指针变量char*数组指针变量数组指针变量是什么数组变量的写法与初始化二维数组传参的本质函数指针变量函数指针变量是什么及创建函数指针变量怎么用两个有趣的代码typedef 关键字函数指针数组函数指针数组的运用——转换表字符指针变量char*我们一般使用char*时是如下使用的intmain(){charcw;char*chc;return0;}这里有char的另一种用法,即可以用char来存放字符串。存放字符串的两种方法运用数组————char arr[ ] …运用字符指针变量如下intmain(){char*chabcdefg;//“abcdefg是常量字符串指针变量ch存放的是a的地址printf(%c,*ch);//这里打印的是aprintf(%s,*ch);//这里打印的是abcdefgreturn0;}不过即然说了abcdefg是常量字符串所以它是不能更改的。为了严谨性和避免程序崩溃我们一般在char* ch前添加const以表明不能修改。下面再分享一道题加深理解#includestdio.hintmain(){charstr1[]hello bit.;charstr2[]hello bit.;constchar*str3hello bit.;constchar*str4hello bit.;if(str1str2)printf(str1 and str2 are same\n);elseprintf(str1 and str2 are not same\n);if(str3str4)printf(str3 and str4 are same\n);elseprintf(str3 and str4 are not same\n);return0;}结果str1与str2因为str1与str2是数组它们先向内存申请空间地址再存放hello bit. 它们只是存放的的内容相同但是str1与str2比较的本质是数组的起始地址所以结果是are not samestr3与str4这里str3和str4指向的是一个同一个常量字符串。C/C会把常量字符串存储到单独的一个内存区域当几个指针指向同⼀个字符串的时候他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同str3和str4相同。同理字符指针数组intmian(){char*pp[3]{abcd,hijk,wml};//pp[1]存的是字符a的地址//pp[2]存的是字符h的地址//pp[3]存的是字符w的地址return0;}数组指针变量数组指针变量是什么先申明数组指针变量是指针具体是什么见如下类比整型指针int*p 指向整型变量的指针存放的是整型变量的地址 字符指针char*p 指向字符变量的指针存放的是字符变量的地址 数组指针int(*p)[5]arr 指向数组的指针里面存放的是数组的地址注意区分前面所学的指针数组它表示存放指针变量的数组。数组变量的写法与初始化intmain(){intarr[3]{1,2,3};int(*p)[5]arr;//数组名 是整个数组的地址return0;}理解为什么是p): 因为*与p在一起才能表示p是指针变量如果不加就变成了intp[3]此时*与int在一起了p成指针数组了。[参数] :表明指向的数组有几个元素。intmain(){chararr[3]{a,b,c};char(*p)[3]arr;return0;}以上也是一个数组变量二维数组传参的本质voidtest(arr[3][5],inta,intb){inti0;intj0;for(i0;ia;i){for(j0;jb;j0){printf(%d ,arr[i][j]);}printf(\n);}intmain(){intarr[3][5]{{1,2,3,4,5},{2,3,4,5,6},{8,9,5,4,5}};test(arr,3,5);return0;}前文所说二维数组的元素是一维数组每一行所以当二维数组传参时传的也是首元素的地址即第一行一维数组。所以函数对二维数组传参的接收有另一种写法voidtest(int(*p)[5],inta,intb)//接收的是第一行代表的一维数组的地址{inti0;intj0;for(i0;ia;i){for(j0;jb;j0){printf(%d ,*((*arri)j))://数组地址-与数组中每一个元素-不同}printf(\n);}函数指针变量函数指针变量是什么及创建类比前文函数指针————指向函数的指针变量用来存放函数的地址。voidtest();intmain(){printf(%p,test);//打印的是函数的地址printf(%p,test);//打印的是函数的地址return0;}不同于数组数组名是数组首元素的地址函数名是函数的地址数组名是数组的地址函数名是函数的地址下面是函数指针的写法voidtest(intx,inty);intmain(){void(*p)(intx,inty)test//P1 P2 P3return0;P1:与指向函数的返回类型有关P2指针变量的名字P3:与指向函数的参数有关该指针变量的类型为 void(*)(int x,int y)即去掉指针变量的名字函数指针变量怎么用函数指针变量是通过解引用来使用的一般有两种解引用(*p)(传入的参数: *p)就等效于函数本身注意括号不能少。p传入的参数p就等效于函数本身这里可以不用解引用操作符*仅限函数指针#includestdio.hintAdd(intx,inty){returnxy);}intmain(){inta3;intb5;int(*p)(intx,inty)Add;//也可以是Addintr(*p)(a,b);//int r p(a,b);printf(%d,r);//打印的结果是8。如上展示了函数指针变量解引用的用法。两个有趣的代码(*((void)(*)())0)();上述代码实质是调用0地址代表的函数。(void)(*)()是强制类型转换将0转换为一个函数指针它此时代表着0地址的函数。而( *((void)(*)())0) ()是在调用这个函数指针这个函数没有返回值也没有参数。void(*signal(int,void(*)(int)))(int);上述代码是一个函数声明。一个signal函数传参类型是int和void(*)(int)类型的它的返回类型是外围的void(*)(int)类型的typedef 关键字typedef 能够重新将复杂的类型重命名下面将展示常见的typedef用法简化一些复杂的类型typedefunsignedintunit;unit a7;//或者简化数组指针typedefint(*ptr_t)[5];//c语言语法不能写成typedef int(*)[5] ptr_tintarr[5]{0};ptr_tparr;//或者简化函数指针typedefvoid(*ptr_t)(int);//不能写成typedef void(*)(int)ptr_tptr_tsignal(int,ptr_t);函数指针数组当我们想要用到一个可以用来存放函数指针的数组时就需要函数指针数组intAdd(intx,inty){}intSub(intx,inty){}intMul(intx,inty){}intDiv(intx,inty){}intmain(){int(*per[4])(int,int){Add,Sub,Div,Mul};和数组的写法 类型数组名[ 参数 ]类似int(*)(int,int)是数组的类型per是数组名。该数组中存放的函数指针都是**int(*)(int,int)**类型的。函数指针数组的运用——转换表#includestdio.hintadd(inta,intb){returnab;}intsub(inta,intb){returna-b;}intmul(inta,intb){returna*b;}intdiv(inta,intb){returna/b;}intmain(){intx,y;intinput1;intret0;int(*p[5])(intx,inty){0,add,sub,mul,div};//转移表do{printf(*************************\n);printf( 1:add 2:sub \n);printf( 3:mul 4:div \n);printf( 0:exit \n);printf(*************************\n);printf(请选择);scanf(%d,input);if((input4input1)){printf(输⼊操作数);scanf(%d %d,x,y);ret(*p[input])(x,y);printf(ret %d\n,ret);}elseif(input0){printf(退出计算器\n);}else{printf(输⼊有误\n);}}while(input);return0;}以上通过输入一个数找到对应函数指针数组里的函数并且调用该函数这种类似跳转的感觉就是转换表局限性只有返回类型和参数类型相同的函数才能存入数组
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Codex 安装部署全攻略:CLI、VS Code 与 API 配置避坑指南 2026/10/1 9:57:39

Codex 安装部署全攻略:CLI、VS Code 与 API 配置避坑指南

1. 为什么 2026 年还要认真折腾一次 Codex 部署先把话说在前头:Codex 这类 AI 编程助手,真正拉开差距的地方从来不是“能不能用”,而是“能不能稳定、低延迟、按你自己的习惯用起来”。我见过太多人卡在第一步——装完了,但 CLI 跑…

阅读更多 →
Unity手游iOS深链:URL Scheme与Universal Links实践 2026/10/1 9:57:39

Unity手游iOS深链:URL Scheme与Universal Links实践

做手游买量和社交裂变的朋友,应该都绕不开 Deep Link 这个词:用户手机里明明装着你家的 App,但此刻他在浏览器、在聊天框、在广告落地页,你丢过去一个链接,点一下能不能把游戏唤起,还能把邀请码、渠道号一起…

阅读更多 →
VS Code 统一调度三个 AI 编程 Agent:tasks、快捷键与鼠标手势完整方案 2026/10/1 9:57:39

VS Code 统一调度三个 AI 编程 Agent:tasks、快捷键与鼠标手势完整方案

手上同时维护一个多模块仓库,用三个 AI 编程 agent 配合干活:Claude 负责架构梳理和长文本重构,Codex 处理批量代码改动,Pi 跑轻量问答和本地模型任务。之前每次想换一个,要么再开一个终端窗口,要么切到另一…

阅读更多 →
具身智能协同演化动力学(36):形变物体和精密装配中的力觉推演与自主进化 2026/10/1 9:57:39

具身智能协同演化动力学(36):形变物体和精密装配中的力觉推演与自主进化

前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的新型工业视觉系统,也是当前最具代表性的具身视觉技术之一。它有机融合深度强化学习&…

阅读更多 →
具身智能协同演化动力学(40):三体递归架构重新定义产业化新标准 2026/10/1 9:57:39

具身智能协同演化动力学(40):三体递归架构重新定义产业化新标准

前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的新型工业视觉系统,也是当前最具代表性的具身视觉技术之一。它有机融合深度强化学习&…

阅读更多 →
Unity SRP底层原理与Shader开发实战:从内置管线到可编程渲染管线 2026/10/1 9:57:32

Unity SRP底层原理与Shader开发实战:从内置管线到可编程渲染管线

1. 从一次渲染异常说起:为什么要啃SRP的底层 很多人第一次接触Unity Shader,都是从Surface Shader或者直接抄一个片元着色器改改颜色开始的。我当初也一样,觉得能写出一个带边缘光、能接受阴影的Shader就算入门了。直到有一次项目里需要做一套…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉