曾经的我是一个摆男,一言不合就开摆,直到我遇见了电子厂。。。。发生了一些不可描述的事,让我看清了社会的真相。。。 

进入正题!

分析时的两个步骤:是什么?怎么用?

是什么?

1、指针数组:本质是数组,数组中存储的每个元素是指针

怎么用?

以遍历数值指针数组为例,int* arr[4] = { &num1,&num2,&num3,&num4 };就是数值指针数组

  void t1(){int num1 = 10;int num2 = 20;int num3 = 30;int num4 = 40;int* arr[4] = { &num1,&num2,&num3,&num4 };int n = sizeof(arr) / sizeof(arr[0]);int i = 0;for (i = 0;i < n;i++){printf("%3d", *arr[i]);}printf("\n");}int main(int argc,char *argv[]){t1();return 0;}

输出的时候为:*arr[i]   因为*()等价于[],所以也可以写成:**(arr + i)

这里讲一下:&arr[i] == (arr + i)     然后*arr[i] == **(arr + i)

不要搞混了

以遍历字符串指针数组为例,int* arr[4] = { "tienan","nuoshou","wanhao","jianmo" };就是字符串指针数组

#include <stdio.h>void t2()
{char *arr[4] = {"tienan","nuoshou","wanhao","jianmo",};char* brr[4] = { "铁男","诺手","腕豪","剑魔" };int n = sizeof(arr) / sizeof(arr[0]);int i = 0;for (i = 0;i < n;i++){printf("%10s", arr[i]);//printf("%10s",*(arr + i));//选一种输出即可}printf("\n");for (i = 0;i < n;i++){printf("%10s", brr[i]);}printf("\n");//想把tienan的e打印出来怎么办?/***************难点******************///第一种,数组的方式printf("%10c\n",*(arr[0] + 2));
//解析:arr[0]是“tienan”这个首元素的首字母地址,直接指向t,+2之后指向e,把e的打出来取*//第二种,指针的方式printf("%10c\n",*(*arr + 2));
//解析:arr是数组首元素地址,指向第一个元素,也就是”tienan“,*arr是取到第一个元素的第一个字母内容,也就是t,也就是*arr 和arr[0]等价,再+2之后指向e,把e打印出来再取*//思考:下面这个输出什么?printf("%10c\n",**arr + 2);printf("\n");
}
int main(int argc,char *argv[])
{t2();return 0;
}
​

输出的时候为:arr[i]

因为字符串输出的时候是给首地址,所以输出少一个  *

为什么输出的是v? 因为*arr是取到 t 嘛,再取 * 是把它打印出来,**arr + 2就是打印 t 后面ASCII码值 +2 的字母。

 arr是数组的首元素地址,&arr是数组的首地址,它们两个表示的地址相同,但是概念不同。对首地址取 * ,得到数组首元素地址。也就是说 *&arr 和 arr 等价。所以,对首地址 +1 ,偏移一个数组;对首元素 +1 ,偏移一个元素,对 *(首元素) +1 ,偏移一个字母。BUT!!对于数组指针来说,数组名只代表第0行的行地址(有些人说是第一行,无所谓,就是最开始的那一行),接下来要讲的是数组指针

继续!

2、数组指针:本质是指针,指向一个数组,指针的值是数组的地址

以数组指针遍历数值数组元素为例

#include <stdio.h>
void t3()
{int arr[2][3] = {1,2,3,4,5,6};int (*p)[3] = arr;//写成int (*p)[3] = &arr;也行,但是要报警告//写成int (*p)[3] = NULL;p = arr也行,这个不报警告//下面输出0行1列元素,也就是2,两种方式可任选一种printf("arr[0][1] = %d\n",*(*(p + 0) + 1));//*(*(p+0) + 1) == *(arr[0] + 1) == arr[0][1]//printf("arr[0][1] = %d\n",arr[0][1]);//这种是数组的方式//下面看+1后偏移多少printf("arr[0][0] = %d\n",**p);printf("arr[a][b] = %d\n",*(*(p+0)+0) + 1);//(**p + 1)printf("arr[c][d] = %d\n",**(p + 1));printf("arr[e][f] = %d\n",*(*p + 1));//下面看指向的地址printf("%p\n",**p);printf("%p\n",**p + 1);printf("%p\n",**(p + 1));printf("%p\n",*(*p + 1));//下面是数组指针遍历数组元素int i,j;for(i = 0;i < 2;i++){for(j = 0;j < 3;j++){printf("%3d",*(*(p + i) + j));//printf("%3d",arr[i][j]);}}printf("\n");//也可以用这种方式连续输出for(i = 0;i < 6;i++){printf("%3d",*(*p + i));}printf("\n");
}
int main(int argc, char *argv[])
{ t3();return 0;
} 

继续!

3、函数指针:本质是指针,指向一个函数,指针的值是函数的地址

以下是函数指针普通用法

 #include <stdio.h>int fun_jia(int a,int b){return a+b;}void t4(){int (*p)(int,int) = fun_jia;//写成int (*p)(int a,int b)也行//写成int (*p)(int x,int y) = &fun_jia;也行//写成int (*p)(int x,int y) = fun_jia;也行//写成int (*p)(int,int) = NULL;p = fun_jia;也行printf("%d\n",fun_jia(1,2));//输出的fun_jia(1,2)不能取地址!}int main(int argc, char *argv[]){   t4();return 0;}

以下是函数指针进阶用法

 #include <stdio.h>int fun_jia(int a,int b){int c = a + b;return c;//或者直接写成return a + b;}int fun_jian(int a,int b){return a - b;}
//新定义一个函数,用函数指针调用上面定义的函数int func(int a,int b,int(*p)(int,int)){return p(a,b);}void t4(){printf("%2d\n",func(1,2,fun_jia));printf("%2d\n",func(1,2,fun_jian));}int main(int argc, char *argv[]){t4();return 0;}

注意:上面我没写函数申明,但依然没有问题。是因为主函数在最下面。

继续!

4、指针函数:本质是函数,函数的返回值是指针。

 #include <stdio.h>#include <stdlib.h>//malloc要用#include <string.h>//memset要用int *fun_jia(int a,int b);int *fun_jia(int a,int b){   int *p = (int *)malloc(sizeof(int));//在堆区申请空间,但不自动清0if(p == NULL)//预防空间申请失败,堆区满了就可能失败{return 0;//如果没有这个判断语句,如果p == NULL,就会报错}   memset(p,0,sizeof(int));//手动清0*p = a + b;return p;free(p);//释放堆区空间,不想用了就释放}   void t5(){int *p = fun_jia(1,2);//int *p = NULL;//p = fun_jia(1,2);//写成int *p = fun_jia(1,2);也行printf("%d\n",*p);}int main(int argc, char *argv[]){t5();return 0;}

继续!

5、函数指针数组:本质是数组,每个元素是函数地址,指针指向一个函数,指针的值是函数的地址,相当于函数指针int(*p)(int,int)  = fun_jia;组合成数组的形式!而函数指针数组指针(指向函数指针数组的指针),它的每个元素是函数指针。别搞混了。。。

 #include <stdio.h>int fun_jia(int a,int b);int fun_jian(int a,int b);int fun_jia(int a,int b){return a+b;}int fun_jian(int a,int b){return a-b;}void t6(){int (*p[2])(int,int) = {fun_jia,fun_jian};//定义函数指针数组//数组肯定要遍历嘛int i;for(i = 0;i < 2;i++){printf("%3d",p[i](1,2));}printf("\n");}int main(int argc, char *argv[]){t6();return 0;}

这里输入写成:int (*p[2])(int,int) = {&fun_jia,&fun_jian}; 也行。

这里输出写成:printf("%3d",(*(p + i))(1,2)); 也行。

难吗,不难!只写了4个小时。睡觉!

指针数组,数组指针,函数指针、指针函数、函数指针数组相关推荐

  1. c++函数内部可以返回函数内部定义的指针 但是不能返回函数内部定义的数组...

    1.返回数组 // demo.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<stdio.h> char *m ...

  2. 【C 语言】二级指针作为输入 ( 二维数组 | 抽象业务函数 | 二维数组打印函数 | 二维数组排序函数 )

    文章目录 一.抽象 二维数组 业务函数 1.二维数组 打印函数 2.二维数组 排序函数 二.完整代码示例 一.抽象 二维数组 业务函数 1.二维数组 打印函数 注意 , 二维数组 作为 函数参数 输入 ...

  3. 【C 语言】一级指针 易犯错误 模型 ( 判定指针合法性 | 数组越界 | 不断修改指针变量值 | 函数中将栈内存数组返回 | 函数间接赋值形参操作 | 指针取值与自增操作 )

    文章目录 一.判定指针合法性 二.数组越界 三.不断修改指针变量值 四.函数中将栈内存数组返回 五.函数间接赋值形参操作 六.指针取值与自增操作 一.判定指针合法性 判定指针合法性时 , 必须进行如下 ...

  4. 指针数组的初始化和遍历,并且通过for循环方式、函数传参方式进行指针数组的遍历...

    1 /************************************************************************* 2 > File Name: messa ...

  5. 剖析数组名、函数名(不是指针常量,更不是指针)

    对于一个数组,如 int a[4];  如果只是给出数组名a,编译器不知道该取该数组的第几个元素,因此编译器不会自动取值,而是返回该数组的首地址(第一个元素的地址).其实,数组名a就是数组本身,并不是 ...

  6. 【C语言进阶深度学习记录】三十一 数组作为函数参数时退化为指针

    之前的学习数组的文章中,已经知道一维数组作为函数参数的时候,最终会被编译器编译为指针.今天来看看二维数组的情形 文章目录 1 为什么C语言中的数组作为函数参数会退化为指针? 2 二维数组作为函数参数如 ...

  7. C++(12)--函数基础:按值传递、传递数组、函数指针

    模块化编程--函数 1. 函数基本知识 2. 函数的参数 2.1 按值传递机制(小议按引用传递) 2.2 使用数组做函数参数(用户头文件,const的防改) 2.3 使用二维数组作为函数的参数 2.4 ...

  8. 常量 数组 函数 枚举 结构体与指针

    与指针括起来的是指针(*a) int const *a = &b; /* 常量指针 */ int (*a)[5]; /* 数组指针 */ int (*add)(int a, int b); / ...

  9. 【C语言指针】 回调函数、冒泡函数模拟实现qsort、指针和数组笔试题解析

    目录 一.回调函数 定义: 用回调函数形式实现加法运算 二.qsort 函数参数: void指针 用qsort排序整型和结构体 用冒泡函数模拟实现qsort,排序整型和结构体 三.指针和数组笔试题解析 ...

  10. 函数指针,函数指针数组,函数返回值为函数指针

    函数的名字就是函数的首地址:定义函数指针; int (*p)(int )     p为函数指针变量名字,int 为函数的返回值类型为int型:(int)为函数的形参类型为int型, 注:因为优先级所以 ...

最新文章

  1. 3D Touch介绍: 一个数字压力器App和Quick Actions
  2. 树莓派连接显示器不亮屏的解决方案
  3. javascript的族家族史
  4. Magic Leap大举进军AR医疗:新品率先与医疗机构合作,挖走HoloLens老客户
  5. 基本概念,BGP协议的特征和消息类型,状态转换?
  6. UBUNTU安装 Rabbitvsc可视化版本控制客户端软件
  7. ArcGIS实验教程——实验十三:栅格空间插值分析
  8. 【汇编语言】王爽实验8,分析一个奇怪的程序,学习笔记(20200517)
  9. 小米又给员工发福利了! 逾3亿港元457人分
  10. 数字资产价值巨大,GMQGroup深入布局挖掘数字财富
  11. 12bit的图像如何向8bit转化_光端机该如何配置?
  12. OBS 录制黑屏的解决方法
  13. Infor SyteLine ERP 安装后中文语言设置
  14. 支配树 Dominator Tree
  15. Edge检查更新时出错:无法连接到Internet。如果使用防火墙,请将 MicrosoftEdgeUpdate.exe 加入允许列表中。
  16. 关于模拟京东二维码登录失败的解决方案
  17. 天之博特 多车协同:Waiting for subscriber to connect to /tianbot_1/cmd_vel 解决办法
  18. post-processing effects HDR
  19. FlatBuffer
  20. AnyTXT 一款强大的本地文件内容搜索软件

热门文章

  1. 英文论文写作注意事项
  2. Greenplum数据库集群安装指南
  3. pipenv 虚拟环境 Django项目部署
  4. Vue中自定义弹窗组件
  5. Unity之语音识别
  6. Carla自动驾驶模拟器快捷键指令
  7. 计算机视觉学习资料汇总(超多干货)
  8. 流浪者变潮人,犀利哥犀利姐引发乞丐风潮
  9. Redis面试连环炮,你能撑到第几关?(持续更新中)
  10. 国家的名字可以如此...浪漫