如何熟悉网站项目的逻辑,门户网站建设自评报告,新乡网络推广外包,东莞住建局备案查询1、字符指针变量 指针类型中我们知道有一种为字符指针char*的指针类型#xff0c;其使用方法如下#xff1a; 上面我们是先将字符使用一个变量#xff0c;然后将变量的地址传给一个字符指针变量#xff0c;通过指针变 量实现了对这个字符的打印。还有下面的这种…1、字符指针变量 指针类型中我们知道有一种为字符指针char*的指针类型其使用方法如下 上面我们是先将字符使用一个变量然后将变量的地址传给一个字符指针变量通过指针变 量实现了对这个字符的打印。还有下面的这种方法 上述的代码很很多人可能会认为是将字符串hello word放在了字符指针ps中了其实不 然其本质上是将字符串的首字符的地址放在了ps指针中如下图所示 下面我们看一道《剑指offer》中的一道和字符串有关的笔试题 我们来对这个代码进行一个分析 这里的str3和str4指向的是同一个常量字符串。在c\c中会把常量字符串存储到一个单独 的内存区域当几个指针变量去指向同一个字符串常量的时候他们实际上会指向同一 块内存。但是用相同的常量字符串的初始化不同数组的时候就会开辟出不同的内存块。 所以str1和str2的地址是不同的而str3和str4的地址是一样的。 所以其输出的结果如下 2、数组指针变量 1、数组指针的定义 前面我们学习了指针数组指针数组是一种数组数组中存放的是地址指针 那么数组指针是什么呢是指针变量还是数组呢 其是指针变量。 前面我们已经熟悉了 整型指针变量存放的是整型变量的地址能够指向整型数据的指针。 浮点型指针变量存放的是浮点型变量的地址能够指向浮点型数据的指针。 那么数组指针就应该是存放数组的地址的指针能够指向数组的指针。 那么数组指针的写法是咋样的呢 我们看下面两个写法 int *p1[10]; int (*p2)[10]; 这里我们思考一下p1和p2都是数组指针吗 我们先来看第一个、这里的*号会和前面的int结合因为[]操作符的优先级是比*号要高的 那么就导致了p1是和后面的[10]结合的*和int结合那么就是一个指针数组。 而第二个的话p2和*是用小括号括在一起的那么就改变了整个表达式的优先级此时的* 是和p2结合的那么此时的p2是一个数组指针其指向的是一个数组。 所以数组指针变量的定义方法如下 int (*p)[10];
2、数组指针的初始化 数组指针变量是用来存放数组的地址的那么我们可以使用前面所学习的取地址符号来取 数组的地址如下 整个表达式的具体情况如下 前面我们也对数组的取地址进行了详细的说明了如果有不懂的同学可以看前面的内容。
3、二维数组传参的本质 前面我们有了数组指针变量的的理解我们就来学习一个二维数组传参的本质。 过去我们需要二维数组做为参数的时候是下面这样写的 如上我们要定义一个函数要实现的功能是将二维数组成行的打印出来。那么要将二维数 组作为参数其此形参和实参都写成了二维数组的形式那么我们还有其它的写法吗 我们再对二维数组进行理解二维数组可以看成一维数组其元素是一维数组。我们在传 参的时候都会传这二维数组的数组名我们也都知道一个数组的数组名是首元素的地址 那么二维数组又可以看成是 一维数组的数组那么此时二维数组的首元素的地址是什么 呢 根据数组名就是首元素的地址这个规则那么二维数组的数组名就是其第一行元素的地 址是一维数组的地址。那么根据我们上面的例子第一行的一维数组就是int[5]所以 第一行的地址就是数组指针类型int (*)[5]那么也就是说二维数组传参的本质也是传地 址传递的是二维数组第一行数组的地址那么我们形参可以写成数组指针的形式来接 收这个地址。如下所示 运行结果如下 可以看到我们使用数组指针的方式来接收这二维数组也可以将这个数组完全打印出来 我们上面的代码只是将形参改变了我们是否可以使用解引用的方式就数组的元素进行 打印呢下面我们来分析一下 前面我们说到二维数组可以看成元素是一维数组的一维数组 那么这个一维数组名字 是啥呢 第一行的数组名arr[0], 同理第二行数组名arr[1]第三行数组名arr[2]。 那么*p0,*(p1)*(p2)分别就是第一行第一个元素第二行第一个元素第三行 第一个元素即*p0arr[0]*(p1)arr[1]*p2arr[2]。 那么就是每一行的首元素地址我们就都有了那么我们再对其进行1操作就可以访问到其 一行上的元素了。 例如*(*p0 1)就是第一行第二个元素了。 下面我们通过代码来看看 运行结果如下 综上二维数组传参形参的部分可以写成二维数组也可以写成指针形式因为数 组传参的本质还是地址传递 。
4、函数指针变量
1、函数指针变量的创建 什么是函数指针变量呢 在前面我们学习了整型指针数组指针的时候我们举一反三不难得到函数指针就是用来存 放函数地址的指针变量未来我们需要使用这个函数可以通过这个指针来调用这个函数的。 那么函数是否也是有地址的呢下面我们通过代码来验证一下 运行结果 可以看到确实将函数的地址打印出来了而且我们还发现函数名就是函数的地址当然也可 以通过函数名的方式取得函数的地址。 如果我们要将函数的地址存储起来那么我们可以通过函数指针来存放函数指针的写法和 整型指针的写法类似。 下面我们通过代码的方式来理解 首先就是指针的类型是要和函数的返回值类型一样的例如上面的返回值为整型那么函数指 针的类型也是为整型如果无返回值那么函数指针的类型也会无返回值类型void。然后就 是那个* 符号应该和名字一起放在一个小括号内。 然后就是对于无参数的函数其定义指针变量的时候就没什么特别要求了。 有参数的函数对于接收其地址的指针变量的定义则也要和函数一样将其参数写出来。 下图是关于函数指针的解析 2、函数指针的使用 可以通过函数指针来实现函数的调用由于函数名就是函数的地址所以我们在使用时可以 直接使用函数指针变量替换函数名。 下面我们通过一个例子来理解 输出结果 我们还可以对p进行解引用这样也可以拿到函数add的地址。 运行结果 3、两段有趣的代码 代码1 这个代码我们一眼看去就会很懵逼不知道从何下手。我们可以从其 特殊的部分出发这段 代码中最特殊的就是那个0了我们从0将这个代码分开来看。 其左边部分为void(*)()) 很明显这是一个函数指针类型其放在0的前面的作用是什么呢 这是一个强制类型转换例如int3.14;在这个浮点数前面加上一个括号括号里面加上 需要转换的数据类型就可以将这个数据转换为括号内的类型了。 那么上述的代码也就是将这个0强制转换为一个函数指针类型那么此时的0就是一个指针 然后前面的*号就是对其解引用后面的小括号就是函数本身。 综上所述上述代码其实就是一个函数。只是这个函数没有参数。 代码2 void * signal ( int , void ( * ) ( int ) ) ( int ) ; 我们首先从signal入手这个看起来和一个函数声明一样他的参数分别是一个整型数据还 有一个函数指针。 那么剩下的是什么呢 我们将中间已经解析的部分去掉、 void*int; 很明显这个部分也是一个函数指针其实这是signal这个函数的返回类型那么其为何不和我 们前面学习到的函数定义那个部分那样去写呢void (*) (int) sighnal(int,void(*)(int)); 这样似乎更加容易读懂。但是在c语言中未定义的所以还是要使用一开始定义方式不可以 使用修改的那个定义方式。 综上所述这段代码是对函数sighnal的声明他是参数为一个整型数据一个函数指针 其返回类型会函数指针。
5、typedef关键字 typedef就是type define他是用来对类型重命名的可以将复杂的类型简单化。 比如说我们觉得unsigned int 这个类型写的话不是很方便那么我们使用typedef关键字对 其重命名命名成自己觉得合适的名字。下面我们来演示一遍给你看看。 这个关键字对于指针类型也是适用的 写法和上面是一样的typedef int* prt_t; 上述的代码我们就将整型指针类型重命名为prt_t了。 不过对于数组指针和函数指针的重命名就有一些差异了。 例如我们现在有一个数组指针类型int (*)[5];需要将其重命名为arr;写法如下 typedef int(*arr) [5]; 对于函数指针void(*)(int)的重命名方式如下 typedef void(*pri_t)(int) ; 那么我们在前面看到的有趣的代码2中我们可以进行一个优化使得其易懂一些 typedef void (*pri_t)(int); pri_t signal(int , pri_t); 这样就更加容易读懂了。 6、函数指针数组 数组是存放相同类型数据的存储空间前面我们已经学习了指针数组是用来存放指针的。 那么函数指针数组顾名思义也就是用来存放函数指针的。 那么函数指针数组是如何定义呢 下面有三种定义方式我们看看那种是正确的。 可以看到编译器就已经对第二第三种报错了这是为什么呢 parr1先和[]结合说明parr1是数组数组存放的数据类型是什么就是int (*)()类型是存放 返回值类型为整型的函数的地址。 下面我们通过一个实例来感受函数指针数组的作用。
7、转移表 函数指针的用途转移表 例计算器的实现要求可以使用户通过选择是实现简单的加减乘除的运算。 前面我们写过一个函数是实现求加法运算的。下面我们将其他几个功能也实现。 计算器的实现 下面为简单的方法 通过上面的代码我们是实现了这些功能但是我们在编写的过程可以看到代码中有大量的重 复那么我们可不可以优化一下呢 我们发现这些函数的返回类型和参数的个数和类型都是一样的。那么我们可以创建一个函数 指针数组。因为要实现四个功能这里我们在数组的创建有个技巧就是将下标为0的用一个 0占用然后这样我们的函数的下标就从1开始了 。 优化后的代码 这样我们看到主函数中的代码整洁多了代码的可读性也高了。