当前位置: 首页 > news >正文

首都博物馆 网站建设产品开发的流程

首都博物馆 网站建设,产品开发的流程,软件开发培训课件,手机qq电脑版登录入口官网目录 1.二级指针 2.指针数组 2.1指针数组的定义和表现形式 2.2指针数组模拟实现二维数组 2.2.1二维数组 2.2.2使用指针数组模拟实现二维数组 3.字符指针 2.数组指针 3.二维数组传参 4.函数指针 4.1函数指针变量的定义和创建 4.2函数指针变量的使用 4.3两段有趣的代码 4.…目录 1.二级指针 2.指针数组 2.1指针数组的定义和表现形式 2.2指针数组模拟实现二维数组 2.2.1二维数组 2.2.2使用指针数组模拟实现二维数组 3.字符指针 2.数组指针 3.二维数组传参 4.函数指针 4.1函数指针变量的定义和创建  4.2函数指针变量的使用 4.3两段有趣的代码 4.4typedef关键字 5.函数指针数组 1.二级指针 我们说指针其实就是一个存放一个变量地址的变量那么指针的本质其实还是一个变量。既然指针是一个变量那么这个变量就应该有属于它的地址既然有一个存放它的地址那么我们也可以套娃把这个地址放在另外应该指针里面那么我们就称这个存放指针地址的另外一个指针为二级指针。 我们可以使用一个生动形象的图来表示这样的关系 这样是不是更好理解了呢 指针无非就是一种专门储存地址的变量再用另外一个指针储存这个变量就构成了二级指针。我们下面看一下指针的初始化结构 int a 10 ;//创建一个变量a int * p a ;//创建一个一级指针p储存a的地址 int * * pp p ;//创建一个二级指针储存一级指针的地址我们在前面讲过在指针这部分使用类比推理法是一个很有力的工具我们再使用类比推理法来解析一下创建二级指针的结构 这就是一个二级指针对于二级指针的运算其实和一级指针是互通的也就是通过解引用操作符*回到上一级通过取地址操作符取得地址*和 仍然可以相互抵消。比如我们使用**pp其实就是得到了a的值因为这里*pp表示通过解引用操作符找到一级指针p然后**pp就是通过对这个一级指针p解引用得到a的值。 在这里我们就可以这样使用这种二级指针两次解引用看一下能不能打印出变量的值 在这里我们可以清楚的看到 a *p    **pp  10 2.指针数组 2.1指针数组的定义和表现形式 我们在之前学过数组数组里面每个元素都是整形的叫做整形数组数组里面每个元素都是浮点数的叫做叫做浮点数数组那么一个数组里每个元素都是指针的就是指针数组。并且每个指针都应该是一个储存地址的变量单元格所以指针数组本质上其实是每个元素里面都储存了一个指针地址变量。 这样我们其实就可以使用一个指针指向几个指针构成一个指针数组 int a 10;int* pa a;int b 20;int* pb b;int c 30;int* pc c;int d 40;int* pd d;int* arr[4] { pa,pb,pc,pd };//或者我们可以使用另外一种表现形式//int* arr[4] { a, b, c, d }; 要理解这个指针数组其实也不难指针数组本质其实就是数组有整形int数组有浮点型double数组有字符型char数组也就可以有指针数组。当然指针数组是要细分的指针数组还可以分为整形指针int*数组浮点型指针double*数组字符型指针char*数组...... 既然一个指针数组可以存放多个地址那么我们其实也可以存放一个多个数组的首元素地址前面我们又知道一个数组的首元素地址我们通常使用这个数组名来代替那么我们就可以写出下面的代码 int arr1[5] { 1,2,3,4,5 };int arr2[5] { 1,5,8,9,5 };int arr3[5] { 3,6,8,5,1 };int arr4[5] { 3,8,7,6,4 };int arr5[5] { 7,3,5,6,4 };int* parr[5] { arr1,arr2,arr3,arr4,arr5 }; 这样就是指针数组的两种表现形式下面的这个看起来的话其实是有点像二维数组一会儿我们就会讲到其实用指针数组储存的这几个数组的长度可以各不相同这也是使用二维数组无法实现的一个功能但是数组长度各不相同我们就要考虑数组越界的问题了。 这样其实各不相同的所谓“二维数组”的存在其实就非常抽象因为它似乎起不到什么作用。但其实我们总有一天写一些比较特别的代码的时候我们就会用到这样“奇怪”的代码学会这样的表现形式会让我们在后面的学习过程中更加得心应手我们可以运用更加广泛的思维去写出代码没准现在你看起来“没什么用”的代码形式会帮你一个大忙 2.2指针数组模拟实现二维数组 2.2.1二维数组 在我们学习这个指针数组模拟实现二维数组之前我们先回顾一下二维数组的定义 数组的元素都是内置类型的如果我们把⼀维数组做为数组的元 素这时候就是⼆维数组⼆维数组作为数组元素的数组被称为三维数组⼆维数组以上的数组统称 为多维数组。 给定一个二维数组arr[3][5]就表示一个数组有3行5列也就是说前面的arr[3]表示这个数组有3行后面的[5]表示这个数组有5列准确的说一个二维数组是按照行“分割”的 像这样我们把这个3行5列的二维数组按照行“分割”其实就可以看成3部分arr[0]、arr[1]、arr[2],这同时也是这个数组的行号然后就是这三部分每个部分都有一个“头”这就是每行的首元素。 比如我们需要找到第2行第4列的元素我们就要先通过行号找到arr[1]也就是第二行然后就是第4列元素我们就得到了arr[1][3]这里面存储的就是我们想要的元素。 或者我们从地址的方向理解的话其实数组无非就是一系列连续存放的元素罢了这里我们使用一段代码打印一下一个3行5列的每个元素的代码 在这里我们可以看到二维数组确实是连续存放的并且以行作为分割 标志一一存放数组中的每一个元素。所以我可以用下面的图示表示一段二维数组 这样就可以想象出一个二维数组的大概形式了我们的计算机想要找到一个二维数组的元素时先通过寻找行找到这个行首元素的地址然后再通过列定位到这个行里面的元素然后实现二维数组元素的调用。 2.2.2使用指针数组模拟实现二维数组 通过上面我们对二维数组的回顾我们也大概了解了一个二维数组的构成接下来我们可以使用指针数组来模拟实现这个二维数组。需要注意的是我们是使用指针数组模拟实现一个二维数组这个模拟实现的数组其实从根本上来说并不是一个二维数组。 那么我们就可以先列一下我们的思路 首先我们需要实现一个模拟的二维数组我们就需要通过定义几个分开的区域表现行的特性这里我们用几个相应的一维数组来实现然后再通过这个数组的列找到我们想要的元素那么其实我们就可以列出下面的实现原理图 这里parr就是一个指针数组里面储存着arr1arr2arr3也就是这三个数组的首元素地址然后arr1arr2arr3其实模拟的就是一个二维数组的1、2、3行这样我们就得到了这个数组的行和列写一下代码 int arr1[5] { 1,2,3,4,5 };int arr2[5] { 2,3,4,5,6 };int arr3[5] { 3,4,5,6,7 };int* parr[3] {arr1,arr2,arr3}; 我们就通过一段指针数组模拟实现了一个二维数组之所以是模拟实现其实就是这几个一维数组之间其实并不是连续存放的它们直接有一定的空隙所以这个模拟实现的二维数组并不能等同于二维数组。 我们想要通过这个模拟实现的二维数组找到第2行第3列的元素就可以使用p[1]首先找到这个对应“行”的首元素的地址然后就是找到这个对应“列”的地址。 我们在前面对数组曾经剖析过这样的结论一个arr数组配上[ k ] 时其实就是通过首元素地址找到了第k个元素这里计算机会把把 arr[ k ] *( arr k )  得到arr元素的地址加上相应的元素间隔得到了我们要求的元素。 在这里我们又需要用到这方面的知识我们使用parr[ 1 ]就得到了一个地址这个就是arr2的地址在我们的模拟二维数组里面就是第二行的首元素地址在计算机里面就是  *parr 1。我们在想要找到第3列的元素我们就要通过得到的这个parr[ 1 ]再得到第3列的元素在计算机里表示就是**parr 1 2 写出来就是parr[1][2],这样我们就得到了模拟实现的二维数组的第2行第3列的元素用代码实现一下就是 3.字符指针 我们接触了很多指针它们的类型都是int *类型的其实除了int * 型的指针还有很多种类型的指针这里我们主要介绍 char * 型的指针。 char * 型指针就是字符指针字符又分为单字符和字符串这就是组成我们字符指针变量的两种小分类。 单字符使用 char ch G;//定义一个字符储存一个单字符G char * pc ch ;//定义一个字符指针储存上面字符变量ch的地址 字符串使用 char* pstr Hello World;printf(%s\n, pstr); 这里我们运行一下这个通过字符串指针打印的结果 很明显的发现我们打印成功了但是你觉得这个指针pstr里面储存的是整个字符串的地址还是第一个元素的地址呢 这里我们就可以使用打印pstr的地址和pstr 1的地址 这个非常好用的方法很直观的表示了我们pstr其实代表的是字符串里面第一个元素’H‘的地址假设我们这个指针里面储存的是整个字符串我们输出的pstr和pstr1之间的差距就是整个字符串的长度了所以我们可以推断出pstr其实代表的是字符串里面第一个元素’H‘的地址。 在《剑指offer》这本书里面收录了一段这样的代码 #include stdio.h int main() {char str1[] Hello World;char str2[] Hello World;const char *str3 Hello World;const char *str4 Hello World;if(str1 str2)printf(str1 and str2 are same\n);elseprintf(str1 and str2 are not same\n);if(str3 str4)printf(str3 and str4 are same\n);elseprintf(str3 and str4 are not same\n);return 0; }我们运行一下结果 我们发现这里面的str1和str2其实是不一样的地址而str3和str4其实是同一个地址我们再使用打印地址验证这个结论 可以看到其实str1和str2就是两个内容相同的两个不同的字符串str3和str4是两个不同的字符指针指向了同一个字符串这里我们的计算机内存中开辟了三个空间存储同样内容的三个字符串“Hello World”只有字符串指针可以实现两个指指针指向同一个元素的功能做个图示理解就是 2.数组指针 数组指针和指针数组是两个东西按照语法来说的话这两个名字都该加上一个“的”也就是变成数组的指针和指针的数组前者本质上是一个指针是一个存放数组的指针后者本质上是一个数组是存放指针的数组这就是区别。 我们要学习数组指针就要从我们之前学习过的其他指针入手比如前面学的整形指针int*和上面的字符指针char*整形指针是储存整形数据的指针字符指针就是储存字符白变量的指针所以我们也可以推出数组指针就是储存数组的指针 如果我们拿出下面的代码让你分辨一下哪个才是数组指针看一下你能不能分辨出来 int *p1[10]; int (*p2)[10]; 答案其实是上面的是指针数组下面的是数组指针这里我们使用一个图解分析一下 其实这就涉及到一个优先结合的顺序问题了。  首先结合的顺序应该是[]* 1一般来说一个指针数组int * p [10],应该是p优先和[10]结合表示了p[10]是一个数组然后就是int 和 * 结合表示这个p[10]数组里面每一个元素都是int * 类型的指针。也就是说我们的变量p是一个数组数组里面每个元素都是一个指针即地址。 2再来看看数组指针 int (*p) [10] ,其实就是优先级被改变了我们就要先把*和p结合这样我们就得到了一个指针*p然后我们的*p和[10]结合表示了一个数组*p[10],前面的int 修饰这个数组表示我们的数组里面每个元素都是int 类型的。也就是说变量p其实是一个指针指针指向的是一个有10个元素的数组数组里面的每个元素是一个int整形。 我们的主体由变量名字p决定p是什么我们的这个东西就是什么。 还是不理解的话我们就可以举例子 int arr[10]{1,2,3,4,5,6,7,8,9,10}; int (*p)[10]arr; 我们可以使用这个数组指针直接打印出这个数组的每一个元素这就是和指针数组不一样的地方我们看到前面我们介绍的指针数组是每个元素都是一个地址它可以用来指向多个数组首元素地址但是我们这个数组指针更加“专一”数组指针只可以指向一个数组然后每个元素都是这个数组的元素并且一一对应。 3.二维数组传参 当我们使用一个二维数组并把它传给一个函数的时候我们会这样写 #include stdio.h void test(int arr[3][5], int r, int c) {int i 0;int j 0;for (i 0; i r; i){for (j 0; j c; j){printf(%d , arr[i][j]);}printf(\n);} } int main() {int arr[3][5] { {1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7} };test(arr, 3, 5);return 0; }可以看到我们使用二维数组传参时传入了一个二维数组和这个数组的行和列的长度 其实二维数组被行分成几个部分比如arr[3][5]表示有3行5列所以我们把这个数组分成3部分每部分是5个元素。把二维数组的数组名分开来理解就是arr[3][5]中arr[3]其实就可以看作这个二维数组的数组名然后这个数组名arr[0],arr[1],arr[2]其实又可以看作是5个一维数组的首元素地址其实就是三个指针。这三个指针 现在我们有一个一维数组在主函数中我们需要使用test函数打印出这个arr数组里的全部元素我们在test函数里输入的参数就要有数组 arr[](注意这里不能是arr如果是arr就不能表示一个数组这样表示的就是一个普通的整形变量)数组长度 len 在主函数中有一个arr[5]所以我们在主函数传入的参数就是arr,5.这里的arr表示的就是数组的首元素地址当然也可以用arr[0]替换。 #include stdio.h void test(int arr[], int len) {int i 0;for (i 0; i len; i){printf(%d , arr[i]);} } int main() {int arr[5] { 1,2,3,4,5 };test(arr, 5);return 0; } 那么我们可以使用 数组作为test函数的形参我们是不是也可以使用一个指针作为形参呢答案其实是肯定的。我们的确可以使用一个指针作为形参而我们传入的参数还可以是这个首元素地址因为我们test函数里面需要的其实就是这个形参指针里面存储的地址就可以改成下面这样 #include stdio.h void test(int *p, int len) {int i 0;for (i 0; i len; i){printf(%d , p[i]);} } int main() {int arr[5] { 1,2,3,4,5 };test(arr, 5);return 0; }同理我们现在使用一个二维数组传参我们想要在主函数里面定义一个二维数组arr[3][5]我们要使用一个test函数打印出这个二维数组里面的所有元素我们就要传入一个arr[ ][5]表示数组注意这里不能只有一个arr[ ][ ],二维数组传参必须带上每行的元素个数r表示行c表示列我们除了这样传参之外还可以把这个arr[ ][5]前面的arr[ ]用一个指针代替也就是用指针指向前面的每行首元素而且每行必须要有5个元素所以我们就可以使用数组指针一个数组指针指向第一行打印完成这行之后再让数组指针指向下一行的首元素地址再次重复打印操作...这样我们就可以得到打印完的全部元素下面是实现代码 #include stdio.h void test(int (*p)[5],int r,int c) {int i 0;int j 0;for (i 0; i r; i){for (j 0; j c; j){printf(%d ,p[i][j]);//这里也可以写成*(*(pi)j)}printf(\n);//换行} } int main() {int arr[3][5] { {1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7} };test(arr, 3, 5);return 0; } 这样我们就只要在主函数传入首行首元素地址就可以得到整个二维数组的全部元素的打印。 所以二维数组传参形参部分也可以写出数组形式也可以写成指针形式。 4.函数指针 4.1函数指针变量的定义和创建  我们知道了数组指针是指向一个数组的指针那么我们就可以知道函数指针其实就是指向一个函数的指针。 有人可能会疑问函数也有地址吗每次其实函数也是有地址的不信这里打印一个函数地址看看 在这里我们可以看到不仅函数名取地址可以打印出地址我们就直接使用一个函数名也可以打印出地址。 那么既然这个函数有地址的话我们就可以使用一个指针存放这个地址这就要创建一个指针变量了。和数组指针类似又不同我们需要使用把函数指针名放起来还要再在外面加上函数的格式比如上面的test函数我们要把这个test函数的地址放在一个函数指针里面的话就要像下面这样操作 void (*p)() test;//也可以直接写成test 这样就是创建一个函数指针的格式我们也可以打印出来这个地址 其实三者是一样的。 如果换成别的函数又要怎么做呢这里我们定义一个Add函数用来表示两个数相加返回值为int就可以写出下面的代码 #include stdio.h int Add(int x, int y) {return x y; } int main() {int (*p)(int, int) Add;//这里也可以写成Addprintf(%p\n, p);printf(%p\n, Add);printf(%p\n, Add);return 0; } 打印一下结果  再抽象一点定义一个函数 void Fuc(int *p,char str,double x);//定义一个函数 那么我们定义的函数指针就可以这样写 void (*p)(int*,char,double)Fuc;//Fuc也可以写成Fuc 4.2函数指针变量的使用 我们可以通过函数指针来调用我们指针指向的这个函数。 比如我们定义了一个Add函数我们定义一个函数指针怎么使用这个函数指针调用这个函数呢很简单模仿一下我们使用Add函数的样子就可以了。 正常情况我们不使用函数指针就可以这样使用 int Add(int x, int y) {return x y; } int main() {printf(%d, Add(1, 2));return 0; } 这样就是简单的一个函数调用和打印。 那么如果使用函数指针怎么使用呢模仿一下函数调用的格式就好了 int (*p)(int, int) Add;printf(%d\n, (*p)(1, 2)); 然后我们在这里把这个*p12改成p(1,2)其实也是可行的二者其实是等价的。 那么我们可以使用这些代码写出下面的代码并运行一下 这样我们就成功使用函数指针调用了这个函数。 4.3两段有趣的代码 代码1 (*(void (*)())0)(); 代码2 void (*signal(int , void(*)(int)))(int); 乍一看这两段代码似乎很让人头疼但其实只要你好好去分析这两段代码你会发现其实也没有那么难。 代码1可以理解成这样 下面这个代码2就简单描述一下 这里其实可以使用类型重命名来简化这段代码2 4.4typedef关键字 typedefy是用来重命名的关键字我们可以利用这个关键字将复杂的类型简单化 例如unsigned int 写起来很麻烦就可以使用typedefy简化这个unsigned int //简化前 unsigned int a 10 unsigned int b 20 //... //简化后 typedefy unsigned int uint //把unsigned int重命名为uint uint a 10 uint b 20 例如我们想要重命名一个数组指针类型int * [5]重命名为parr_t //简化前 int arr[5] { 1,2,3,4,5 }; int(*p)[5] arr; printf(%d*p[0]); //简化后 typedefy int (*parr_t)[5] ; //简化成parr_t //表达原来的代码 int arr[5] { 1,2,3,4,5 }; parr_t p arr; printf(%d*p[0]); 把相应东西替换一下就好了 这样我们就实现了代码的简化。在代码量小的时候可能类型重命名很麻烦但是当代码量增加或者代码复杂性增加的时候类型重命名就体现出它的优点了 比如我们上面的代码2我们就可以把它使用类型重命名简化 //简化前 void (*signal(int , void(*)(int)))(int); //简化后 typedefy void (*pf_t )(int) ; //把函数指针类型简化成pf_t //最后表达原来的代码 pf_t signal(int , pf_t); 这样就可以逻辑清晰地表达我们的复杂的代码了。 5.函数指针数组 函数指针数组听起来有点绕口其实就是一个函数指针的变化更新把普通的指针变成了指针数组。函数指针数组其实本质上还是一个数组。 我们回顾一下指针数组 int * arr[10] ; //一个数组arr[10]每个元素类型是int * 我们再看一下函数指针 #include stdio.h int Add(int x, int y) {return x y; } int main() {//声明函数指针int(*pf)(int,int) Add;//定义函数指针的时候在等号右边可以使用 函数名 或 函数名//通过函数指针调用函数int ret (*pf)(2, 3);//调用函数指针的时候函数名可以使用 (*pf) 或 pfprintf(%d\n, ret);return 0; } 函数指针的本质其实就是一个指针这个指针指向的是一个函数我们定义了这个函数指针之后可以通过函数指针调用这个函数。 同理我们的函数指针数组其实本质上是一个数组准确的讲应该是指针数组这个指针数组指向的是一个函数数组我们在定义了函数指针数组之后也可以通过指针数组对应的项调用对应项的函数。 也就是说我们从函数指针的单个指针指向一个函数变成了多个指针就是指针构成的数组指向多个函数就是函数构成的数组 #include stdio.h int Add(int x, int y) {return x y; } int Sub(int x, int y) {return x - y; } int Div(int x, int y) {return x / y; } int Mul(int x, int y) {return x * y; } int main() {//声明函数指针数组int(*pfArr[4])(int, int) { Add,Sub,Div,Mul };//可以是pfArr[4]也可以是pfArr[]//通过函数指针数组调用函数int ret1 pfArr[0](6 ,2);int ret2 pfArr[1](6, 2);int ret3 pfArr[2](6, 2);int ret4 pfArr[3](6, 2);printf(62 %d\n, ret1);printf(6-2 %d\n, ret2);printf(6/2 %d\n, ret3);printf(6*2 %d\n, ret4);return 0; }像上面的这个就是定义了一个函数指针数组pfArr[4] ,指向加、减、乘、除 四个函数我们通过这个函数指针数组调用各个函数这样就得到了我们的想要的计算值 其实使用这样的函数指针数组是一种简化代码很好的方法同时函数指针数组也可以在一种数据结构——转移表 里面用来优化程序提高计算效率。
http://www.zqtcl.cn/news/904638/

相关文章:

  • wap网站开发技术怎么做消费信贷网站
  • 公司网站开发外包公司深圳网站建设sz886
  • 中英文网站建设需要懂英语吗电气网站设计
  • 双语网站用什么程序做新网站如何被网站收录
  • 怎么做视频平台网站想开个小说网站怎么做
  • 网站安全监测预警平台建设成效阐述网络营销策略的内容
  • 网站上的qq如何做悬浮沧州做网站的公司
  • 电子商务网站系统规划报告移动商城 网站建设方法方式
  • 网站建设架构选型引擎seo优
  • 什么电脑做网站前段用网站建设工作人员有哪些职责
  • 网站建设技巧网站建设 总结
  • 有站点网络营销平台搜一下百度
  • 沈阳网站建设找德泰诺wordpress 访客计数器
  • 专业网站建设价格分析企业展示型网站建设方案
  • 东丽做网站公司帮做网站的公司
  • 网站的icon图标做多大验证wordpress
  • html制作音乐网站代码已经买了域名怎么做网站
  • 网站做收付款接口山东专业的制作网站
  • 龙岗建设高端网站如何建立网站会员系统吗
  • 中国建设银行的网站色彩wordpress 图片采集器
  • 渭南做网站价格江西省城乡住房建设部网站
  • 个人网站可以做充值安徽建设厅网站首页
  • 技术支持 东莞网站建设石材小企业网站建设查询
  • 政务公开网站建设的亮点和建议wordpress注册怎么设置密码
  • 外贸有哪些网站成都网络营销搜索推广优势
  • 国外mod大型网站财税公司
  • 一个很好的个人网站开发做一个简单网页多少钱
  • 东莞在哪里学网站建设网站建设团队与分工
  • 网站功能插件昆明网站建设技术研发中心
  • 网站开发培训中心 市桥移动端ui