范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

C语言指针与函数

  C语言指针函数
  C语言指针函数就是函数中用到了指针的函数,主要是有以下两种方式以指针为参数的函数以指针为返回值的函数
  指针做函数参数
  学习函数的时候,讲了函数的参数都是值拷贝,在函数里面改变形参的值,实参并不会发生改变。如下图:
  每个函数都有一个独立的栈区,在函数传参的过程中,是把实参的值拷贝给形参,修改形参的值并不能作用到实参。如果想要通过形参改变实参的值,就需要传入实参的地址,可以通过寻址方式作用到实参上,如下图:
  想要修改实参的值,需要传入实参的地址,故想要修改该指针变量的指向需要传入指针变量的地址,也就是二级指针。多级指针中也是依次类推,数据结构中常有二级指针传参。
  示例程序| 传参的方式动态申请一维数组
  传参的方式修改一级指针的值,需要传入二级指针,通过寻址的方式修改一级指针,如下测试代码:#include  #include  #include  void createArray(int** parray, int arrayNum)  {   *parray = (int*)calloc(arrayNum,sizeof(int));   assert(parray); }  int main() {   int* p = NULL;   createArray(&p, 3);   for (int i = 0; i < 3; i++)    {     printf("%d	", p[i]);   }   printf(" ");   return 0; }
  运行结果如下:
  示例程序| 封装函数操作数组
  通常在封装函数操作数字类(int ,float,double,…)数组一定要传入数组长度,操作字符串类通常不需要,因为字符串存在字符串结束标记。例如封装遍历数组函数和字符串比较函数,代码如下:#include  #include  #include  #include  //等效void printArray(int array[], int arrayNum)  void printArray(int* array, int arrayNum)  {   for (int i = 0; i < arrayNum; i++)    {     printf("%d	", array[i]);   }   printf(" "); } int myStrcmp(const char* str1, const char* str2)  {   int i = 0;   int j = 0;   //字符串比较从左往右比,找到不同的字符即可得到比较结果   while (str1[i] == str2[j]&&str1[i] != "")   {     i++;     j++;   }   return str1[i] - str2[j]; } int main() {   int array[5] = { 1,2,3,4,5 };   printArray(array, 5);   printf("%d ", myStrcmp("string1", "string")>0);   printf("%d ", myStrcmp("string", "string")==0);   printf("%d ", myStrcmp("string", "string1")<0);   return 0; }
  运行结果如下:
  当然比较函数你也可以返回0,-1,1,只需要在字符串比较函数中分类讨论下即可。
  指针做函数返回值
  指针当做函数返回值和普通函数一样,只是返回值类型不同而已,既然返回是一个指针,*指针等效变量,故*函数调用也可以等效变量。把指针当做函数返回值注意项:不要返回临时变量的地址可以返回动态申请的空间的地址可以返回静态变量和全局变量的地址
  当函数返回临时变量的地址时,地址中存储的数据随着函数调用完会被回收掉,导致获取垃圾值。如下测试代码:#include  int* testFunc()  {   int number = 1314;   return &number; } int main() {   int* result=testFunc();   //第一次数据做了保留   printf("%d ", *result);   //后续数据被回收了,垃圾值   printf("%d ", *result);   printf("%d ", *result);   return 0; }
  运行结果如下:
  在vs开发工具中会友善给予提醒,希望看到这类提醒当做错误处理,及时改善,友善提醒如下:
  示例程序| 返回值的方式动态申请一维数组
  可以返回动态申请的空间的地址,堆区内存需要调用free函数手动释放,如下测试代码:#include  #include  int* createArray(int arrayNum)  {   int* p = (int *)calloc(arrayNum, sizeof(int));   return p; } int main() {   int* p = NULL;   p = createArray(3);   for (int i = 0; i < 3; i++)    {     printf("%d	", p[i]);   }   free(p);   p = NULL;   return 0; }
  运行结果如下:
  示例程序| 用字符串初始化堆区内存并返回首地址
  其实和数字类的操作没什么太大区别,唯一要注意的是字符串申请统计长度用strlen,申请是可见长度加1,拷贝赋值用strcpy完成,如下测试代码:#include  #include  #include  #include  char* createArray(const char* str)  {   //申请长度是可见度长度+1   unsigned int length = strlen(str)+1;   char* p = (char *)calloc(length, sizeof(int));   assert(p);   //不能直接 p=str,语法没问题但是意义不同   strcpy(p, str);   return p; } int main() {   char* pstr = NULL;   pstr = createArray("coolmoying");   puts(pstr);   free(pstr);   pstr = NULL;   return 0; }
  运行结果如下:
  C语言函数指针
  什么是函数指针
  如果在程序中定义了一个函数,那么在运行时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。获取函数地址有以下两种方式:函数名&函数名
  既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。函数指针的唯一作用就是调用函数,函数指针没有++和 –运算
  如何创建函数指针
  函数返回值类型 (*指针变量名) (函数参数列表);
  简单来说一句话,用(*变量名) 替换函数名,剩下的照抄即可,形参名可写可不写就是函数指针变量。如下函数的函数指针创建:
  如何通过函数指针调用函数
  函数指针可以通过不同的初始化方式,调用除了函数名不同,其他类型相同的所有函数。调用方式有以下两种:直接函数指针名替换函数名去调用函数(*函数指针)替换函数名的方式去调用函数
  推荐使用第一种方式,代码看起来比较简单。如下测试代码:#include  #include  #include  #include  void test()  {   printf("Test "); } void test2()  {   printf("Test2 "); } int Max(int a, int b)  {   return a > b ? a : b; } void printArray(int(*p)[3], int row, int cols)  {   for (int i = 0; i < row; i++)    {     for (int j = 0; j < cols; j++)      {       printf("%d ", p[i][j]);     }     printf(" ");   } } int main() {   //创建函数指针变量   void (*pTest)() = NULL;   int(*pMax)(int a, int b) = NULL;   //参数名可省略   void (*pprint)(int(*)[3], int, int) = NULL;   //函数指针赋值   //两种方式即可   pTest = test;   pTest = &test;   pMax = Max;   pprint = printArray;   //函数指针变量调用函数   //两种方式即可   pTest();   (*pTest)();   printf("%d ",pMax(1, 2));   int array[2][3] = { 1,2,3,4,5,6 };   pprint(array, 2, 3);   //调用除了函数名不同,其他类型相同的所有函数   pTest = &test2;   pTest();   return 0; }
  运行结果如下:
  回调函数
  回调函数就是以函数指针作为某个函数的参数,函数指针比较重要的应用就是回调函数,在Windows SDK,多线程,事件处理中大量用到回调函数。函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。简单讲:回调函数是由别人的函数执行时调用你实现的函数。通俗的讲:你到一个商店买东西,没有货,留给店员电话,有货了,打电话给你,然后你去取货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。如下测试代码:#include  #include  #include  #include  void get()  {   printf("取货成功!!! "); } void wait()  {   printf("等待售货员电话!... "); } void salesperson(bool flag, void(*Doing)())  {   if (flag == true)  //有货    {     printf("通知取货 ");     Doing();   }   else         //无货   {     printf("无货 ");     Doing();   } } int main() {   //通常回调函数有关联的事件   //这里简单用有无货物来做   salesperson(false, wait);   salesperson(true, get);   return 0; }
  通常salesperson是第三方封装好的,我们只需要实现salesperson函数指针,通过salesperson去调用自己的函数,通常别人设计的回调函数都会绑定事件,目前初步接触了解下。运行结果如下:
  C语言万能指针充当函数指针
  万能指针充当函数指针使用前必须要强制类型转换,函数指针的类型就是去掉变量名即可   ,如下测试代码:#include  #include  void test()  {   printf("调用成功!!! "); } int main() {   void* p = test;   //正常指针调用:p();   //test类型: void(*)()   //强转语法:  (类型)(表达式)   ((void(*)())p)();   return 0; }
  运行结果如下:
  复杂函数指针解析
  右左法则
  首先找到标识符,然后往右看,再往左看,每当遇到圆括号时,就应该调转阅读方向,一旦解析完圆括号里面的所有东西,就跳出圆括号,重复这个过程直到整个声明解析完毕。
  示例1| int (*func)(int *p)
  首先找到那个标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明func是一个指针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(*func)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int*类型的形参,返回值类型是 int。
  示例2| int (*func)(int *p, int (*f)(int*))
  func被一对括号包含,且左边有一个*号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一个指向函数的指针,这类函数具有int *和int (*)(int*)这样的形参,返回值为int类型。再来看一看func的形参int (*f)(int*),类似前面的解释,f也是一个函数指针,指向的函数具有int*类型的形参,返回值为int。
  示例3| int (*func[5])(int *p)
  func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针,要注意这里的*不是修饰 func的,而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合,因此*修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int*类型的形参,返回值类型为int。
  示例4| int (*(*func)[5])(int *p)
  func被一个圆括号包含,左边又有一个*,那么func是一个指针,跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针,现在往左看,左边有一个*号,说明这个数组的元素是指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。总结一下就是:func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int*形参,返回值为int类型的函数。
  示例5| int (*(*func)(int *p))[5]
  func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。
  示例6| int (*(*(*func)(int *))[5])(int *)
  func是一个函数指针,这类函数的返回值是一个指向数组的指针,所指向数组的元素也是函数指针,指向的函数具有int*形参,返回值为int。
  实际当中,需要声明一个复杂指针时,如果把整个声明写成上面所示的形式,对程序可读性是一大损害。应该用typedef来对声明逐层分解,增强可读性,如果对typedef不懂的,后续讲解。客观请留步
  如果阁下正好在学习C/C++,看文章比较无聊,不妨关注下关注下小编的视频教程,通俗易懂,深入浅出,一个视频只讲一个知识点。视频不深奥,不需要钻研,在公交、在地铁、在厕所都可以观看,随时随地涨姿势。

一张通关方,涤荡瘀浊,7年老前列腺炎愈,至今未复发前列腺炎属于白淫精浊淋证等,症状表现为排尿不畅,膀胱身为州都之官,封藏津液主要在于膀胱,百病生于气也,膀胱气化不足,则排尿不出,膀胱气化过度,则尿频明显。尿液为津液所生,津液通化,降温了饮食要忌口!建议少吃萝卜和生姜,多吃3样,为入冬打基础降温了饮食要忌口!建议少吃萝卜和白菜,多吃3样,为入冬打基础。哈喽,大家好,我是大厨江一舟,今天又到了和大家分享美食的时刻了,你准备好了吗?最近这几天,我们北方的天气是一天比一天寒13分完败!李楠带队输球,双外援优势反成败笔,首钢窒息防守制胜北京时间10月18日,CBA常规赛继续进行,北京首钢迎战江苏男篮,上半场两队紧咬比分,首钢半场领先7分。江苏在第三节使出双外援,不过首钢却在第三节拉开了分差,最终9582江苏,拿到马尔蒂尼连线舍甫琴科,能否将乌克兰内马尔带回至AC米兰?随着金球奖的落幕,AC米兰与上赛季意甲MVP莱奥的续约迟迟没有敲定,根据米体的报道,AC米兰在谈判时将给球员及经纪团队报价年薪500至550万的新合同,同时承担起一部分球员与老东家音响应该怎么选?干货都在这里!小白也能入门千元价位音响,我到底应该怎么选?!各个都说自己天籁之声,物超所值,应该信谁呐?本期内容都是干货!小白看了能入门!让你买音响不上当一箱体材质音响系统中有三大件,箱体功放和音源,其中箱荣耀畅玩40plus真机曝光,这不是荣耀70的后盖设计?荣耀畅玩40plus真机曝光,这不就是荣耀70的设计?这个手机使用了天玑700处理器,这个处理器只能说还行吧。算是一款入门的5g处理器,720p分辨率的屏幕,只能说还行,这个价位就3599元起!苹果新款iPad价格汇总顶配价格太吓人手机中国新闻10月18日晚,苹果发布了新款iPad2022款iPadProiPad10iPad10WiFi版3599元(64GB)4799元(256GB)蜂窝版4799元(64GB联想ThinkBook1416将推i9版,11月上市IT之家10月18日消息,不久前,联想推出了i9型号的YOGA小新轻薄本。现在,i9版的ThinkBook1416也要来了,预计将在11月上市。IT之家曾报道,今年3月份,联想推出苹果将发布iPadPro11和12。9英寸两款搭载M2芯片产业链传出消息称,苹果将在本周发布全新的iPadPro,和上一代的尺寸定位相同,会分位11英寸和12。9英寸两款。而令人遗憾的是,12。9英寸版本采用miniLED屏幕,但11英寸2022。10。17早安心语,正能量精悍语录句子励志精美短句心语图早上好,今天是2022年10月17日,星期一,农历九月二十二,壬寅年虎年庚戌月癸卯日。前方有路,未来可期,无论要经历什么,记得带上善良和感恩,与温暖和幸福相逢,好事正酿,万物复苏,建设体育强国,为社会提供强大正能量户外草坪上,玩飞盘成为年轻人的运动新潮流下班回到家,不少人跟随网络直播跳起健身操炎炎夏日,室内雪场成为市民避暑娱乐新选择时下,体育健身新项目新形式层出不穷,人民群众参加体育运动健身
中国婚姻怎么了我刚看了一刚新闻,2022年结婚人数为210。7万对,降至1987年的结婚人数。2022年中国总人口为15个亿,1987年才10来个亿。这对中国未来经济,政策会发生很大的变化。对此比较下勇士队和国王队?巴恩斯两队运作方式有相似之处直播吧1月25日讯NBA常规赛,国王在主场以133100大胜灰熊。赛后,哈里森巴恩斯接受了TheAthletic的采访。记者问道你能为我对比一下吗?科尔教练早在2014年就来到了勇坚持写作是我反思和解压的最好方式今天是大年初三,是我2023年坚持5点早起的第23天,今年我的目标是通过写作,赚到一些稿费,能够贴补家用,也不枉自己在写作这条路上的坚持和付出,也让自己更有动力坚持下去。对于写作的备受大妈欢迎的泥色大衣,究竟有何过人之处?看看这篇就明白冬日生活打卡季或许在很多人眼中,到了大妈的年纪就老了,所以很多人并不喜欢别人称呼自己大妈。其实这都是因为那些大红大绿花里胡哨的大妈装,让人对一些中老年人产生了误解。事实上,很多女人我们的东坡我们讲丨苏轼书欧阳修丰乐亭记拓本视频加载中以专家讲作家讲文艺家讲新闻主播讲网络达人讲等方式推动三苏文化认知传播传承。文物简介苏轼书欧阳修丰乐亭记拓本这一件为苏轼书欧阳修丰乐亭记拓本,这篇文章除记述建丰乐亭的经过及腊月二十九的习俗你知道吗?腊月二十九腊月二十九,除夕前一日,俗称小除夕这一天,家置酒宴,人们往来拜访叫别岁且焚香于户外,叫天香,通常要三天。小除夕除夕是指每年农历腊月的最后一天的晚上,它与春节(正月初一)首三点原因,电影中国乒乓票房扑街,宣布撤档!中国乒乓之绝地反击官微发布声明,正式宣布撤档,1月25日起调整为小规模放映,至2月17日恢复正常上映。该片1月24日(大年初三)上映,上映两天票房仅为4036万元。据悉该片投资成本罗马诺尽管被扣分让部分尤文球员有离队可能,但目前还风平浪静直播吧1月24日讯根据此前意大利足协官方消息,尤文图斯因财务造假案被扣除15个联赛积分,斑马军团有权在30天内上诉。近日名记罗马诺在个人专栏谈到了尤文图斯,他表示随着尤文图斯在联赛马尔康是世界球星,还是世界巨星?为什么俱乐部会大度放走金靴?自从武汉三镇以中甲冠军冲超成功之后,很多人认为这支球队还会给大家创造奇迹,果不其然,他们又夺得中超冠军,成为中国足坛另一个传奇,如今他们球队也面临球员离开,去年的金靴马尔康离开已经先给彩礼28。8万,再全部返还?试问有几家能做到?每年一到过年期间除了走亲访友,剩下的基本都是排队相亲。彩礼,高价彩礼又被拉升了好几个热度,尤其是江西高价彩礼。有人说江西高价彩礼只是谣传,现实中并没有那么多。也有人说高价彩礼哪个地