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

太原网站制作深圳东门希尔顿欢朋酒店

太原网站制作,深圳东门希尔顿欢朋酒店,百度云附件 wordpress,抖音营销#x1f308;write in front :#x1f50d;个人主页 #xff1a; 啊森要自信的主页 ✏️真正相信奇迹的家伙#xff0c;本身和奇迹一样了不起啊#xff01; 欢迎大家关注#x1f50d;点赞#x1f44d;收藏⭐️留言#x1f4dd;希望看完我的文章对你有小小的帮助write in front :个人主页 啊森要自信的主页 ✏️真正相信奇迹的家伙本身和奇迹一样了不起啊 欢迎大家关注点赞收藏⭐️留言希望看完我的文章对你有小小的帮助如有错误可以指出让我们一起探讨学习交流一起加油鸭。 文章目录 前言一、 字符指针变量二、⛵️ 数组指针变量2.1 数组指针变量是什么2.2 数组指针变量怎么初始化 三、⛵️⼆维数组传参的本质四、函数指针变量4.1 函数指针变量的创建4.2 函数指针变量的使⽤4.3 两段有趣的代码4.3.1 typedef关键字 五、函数指针数组⚓️总结 前言 通过对前面指针的学习你可能对指针有了一些理解比如数字名的理解然后怎么使用指针来访问数组二级指针指针数组 … 有了这些的理解本小节我们继续深入理解指针啊森将会带你理解字符指针变量数组指针变量二维数组传参的本质函数指针变量和函数指针数组通过这些学习我们最后来通过这些知识来实现转移表话不多说让我们启航 一、 字符指针变量 在C语言中字符指针变量是一种指向字符型数据的指针变量。它可以用来指向一个字符数组的首地址也可以用来指向一个字符型变量的地址。 指针类型为字符指针 char* 字符指针变量的声明和初始化如下所示 char str[] Hello; // 声明一个字符数组 char *ptr; // 声明一个字符指针变量 ptr str; // 将字符数组的首地址赋给字符指针变量通过字符指针变量可以访问和操作字符数组中的元素也可以通过指针运算来访问字符串中的字符。例如 int main() {char str[] Hello;char* ptr;ptr str;printf(%c\n, *ptr); // 输出字符数组的第一个字符printf(%c\n, *(ptr 1)); // 输出字符数组的第二个字符return 0; }当然以上是把字符串放在字符数组里面不过我们可不可以把字符串直接放在指针里面呢当然可以 int main() {const char* pa hello,world;//这⾥是把⼀个字符串放到pa指针变量⾥了吗printf(%s\n, pa);return 0; }思考这⾥是把⼀个字符串放到pa指针变量⾥了吗 当然不是 –代码 const char* pa hello,world; 特别容易让同学以为是把字符串 hello,world 放 到字符指针 pa ⾥了但是本质是把字符串 hello,world. ⾸字符的地址放到了pa中。 这个是内存布局hello,world是一个字符串常量它的值存储在内存中而pa是一个指向这个字符串常量的指针它的值是字符串常量的地址。所以pa存储的值是104也就是hello,world的第一个字符的ASCII码值,以此我们就可以通过第一个字符串常量的地址遍历后面的字符顺藤摸瓜的找到字符\0才停止。 总结代码的意思是把⼀个常量字符串的⾸字符 h 的地址存放到指针变量 pa 中。 《剑指Offer》中收录了一道和字符串相关的笔试题让我们一起来学习一下 #include stdio.h int main() {char str1[] hello bit.;char str2[] hello bit.;const char* str3 hello bit.;const char* str4 hello bit.;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 是字符数组它们分别用hello bit.初始化了两个不同的数组。虽然内容相同但它们占用的内存地址是不同的所以str1 str2 判断为不相等打印str1 and str2 are not same。 str3 和 str4 是字符指针它们都指向同一个字符串常量hello bit.。字符串常量存储在只读内存区域无论如何定义它们的地址是相同的。所以str3 str4 判断为相等打印str3 and str4 are same。 换句话说 - 字符数组比较地址地址不同就不相等。 - 字符串常量比较内容内容相同就相等。 所以结果不同的原因是str1、str2是数组str3、str4是指针它们的比较规则不同。 如果将str3和str4也定义为字符数组则它们的比较结果也会是不相等打印str3 and str4 are not same。 二、⛵️ 数组指针变量 2.1 数组指针变量是什么 之前我们学习了指针数组指针数组是⼀种数组数组中存放的是地址指针。 数组指针变量是指针变量还是数组 答案是指针变量。 我们已经熟悉 • 整形指针变量 int * pa; 存放的是整形变量的地址能够指向整形数据的指针。 • 浮点型指针变量 float * pf; 存放浮点型变量的地址能够指向浮点型数据的指针。 那数组指针变量应该是存放的应该是数组的地址能够指向数组的指针变量。 下⾯代码哪个是数组指针变量 那数组指针变量应该是存放的应该是数组的地址能够指向数组的指针变量。 下⾯代码哪个是数组指针变量 1. int *p1[10];2. int (*p2)[10];思考⼀下p1, p2分别是什么 数组指针变量 数组指针变量 1 int (*p)[10];解释p先和*结合说明p是⼀个指针变量变量然后指着指向的是⼀个⼤⼩为10个整型的数组。所以 p是⼀个指针指向⼀个数组叫 数组指针。 这⾥要注意[]的优先级要⾼于 * 号的所以必须加上 来保证p先和 * 结合。 2.2 数组指针变量怎么初始化 数组指针变量是⽤来存放数组地址的那怎么获得数组的地址呢就是我们之前学习的 数组名 int arr[10] {0}; arr;//得到的就是数组的地址如果要存放个数组的地址就得存放在数组指针变量中如下 1 int(*p)[10] arr;我们调试也能看到 arr 和 p 的类型是完全⼀致的。 数组指针类型解析 1. int (*p) [10] arr;2. | | |3. | | |4. | | p指向数组的元素个数5. | p是数组指针变量名6. p指向的数组的元素类型三、⛵️⼆维数组传参的本质 有了数组指针的理解我们就能够讲⼀下⼆维数组传参的本质了。 过去我们有⼀个⼆维数组的需要传参给⼀个函数的时候我们是这样写的 #include stdio.h void test(int a[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 , a[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; }C语言二维数组传参的本质是 二维数组在传参时会自动退化为一维数组指针。 具体来说 二维数组名代表整个二维数组它其实就是一维数组指针指向该数组的首行地址。 当二维数组作为参数传递给函数时它会自动退化为一维数组指针。 函数内部无法得知传入的参数原本是二维数组它只能看到一个一维数组指针。 举个例子 void func(int arr[][3]) {// arr在这里实际类型是int (*arr)[3] }int main() {int a[4][3] {0};func(a); // a传参时自动退化为一维数组指针return 0; }这里a是二维数组但传给func函数时func内部的arr参数实际上是一个指向int[3]类型一维数组的指针。 所以二维数组传参的本质就是自动退化为一维数组指针。 而数组指针变量它也可以指向二维数组首行地址从而实现对二维数组的操作。 例如 int (*ptr)[3] a; // ptr指向a二维数组的首行所以二维数组传参本质是退化为一维数组指针而数组指针变量也可以指向二维数组两者联系在一起都可以看作是一维数组指针来操作二维数组。 那我们就来试试数组指针变量来遍历数组吧---------- ⾸先我们再次理解⼀下⼆维数组⼆维数组起始可以看做是每个元素是⼀维数组的数组也就是⼆维数组的每个元素是⼀个⼀维数组。那么⼆维数组的⾸元素就是第⼀⾏是个⼀维数组。 如下图 根据数组名是数组首元素的地址这个规则二维数组的数组名表示的就是第一行的地址是一维数组的地址。 根据上面的例子第一行的一维数组的类型就是 int [5] 所以第一行的地址的类型就是数组指针类型 int(*)[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));}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.1 函数指针变量的创建 类比一下 数组指针变量应该是存放的应该是数组的地址能够指向数组的指针变量。 C语言中的函数指针变量是指向函数的指针变量。 函数指针变量的定义格式是 返回类型 (*变量名)(参数类型列表);例如 int (*ptr)(int, char); // ptr是一个指向返回类型为int,参数为int和char的函数的指针函数指针变量和普通指针变量一样它也需要指向具体的函数地址才能调用该函数。 例如 int func(int a, char b) {return a b; }int main() {int (*ptr)(int, char); // 函数指针变量声明ptr func; // 指向func函数ptr(10, a); // 通过函数指针调用func函数return 0; }函数指针变量的主要特点 可以指向不同类型的函数通过它可以调用被指向的函数可以作为函数参数或返回值进行传递常用在回调函数机制中 函数指针变量是用来存放函数地址的通过这个地址可以调用函数。函数确实有地址! #include stdio.hvoid print() {printf(lalala\n); } int main() {printf(test: %p\n, print);printf(test: %p\n, print);return 0; }输出 确实打印出来了地址所以函数是有地址的函数名就是函数的地址当然也可以通过 函数名 的⽅式获得函数的地址。 如果我们要将函数的地址存放起来就得创建函数指针变量咯函数指针变量的写法其实和数组指针⾮常类似。如下 void print() {printf(lalala\n); } void (*pf1)() print; void (*pf2)() print;int Add(int x, int y) {return x y; } int(*pf3)(int, int) Add; int(*pf3)(int x, int y) Add;//x和y写上或者省略都是可以的1. int (*pf3) (int x, int y)2. | | ------------3. | | |4. | | pf3指向函数的参数类型和个数的交代5. | 函数指针变量名6. pf3指向函数的返回类型7. 8. int (*) (int x, int y) //pf3函数指针变量的类型看到这里你可能会发现数组指针变量和函数指针变量其实好像也是差别不大呀 4.2 函数指针变量的使⽤ 通过函数指针调⽤指针指向的函数。 #include stdio.h int Add(int x, int y) {return x y; } int main() {int(*pf3)(int, int) Add;printf(%d\n, (*pf3)(1, 2));printf(%d\n, pf3(3, 4));return 0; }代码输出的结果是一样的为什么这两种方式都可以呢 解释 首先 pf3是一个函数指针变量它指向Add函数。 在C语言中函数指针与一般指针运算方式是一致的。 也就是说对函数指针进行解引用(*pf3)后的结果就是被指向的函数本身。 所以 - (*pf3)(1, 2) - 等价于 解引用pf3,得到Add函数然后调用Add(1, 2) - pf3(3, 4) - 等价于 调用函数指针pf3,它指向的函数Add(3, 4) 两者调用的函数都是Add,参数也一致所以结果是相同的。 函数指针与一般指针在语法上表现形式不同但本质上都是指向函数地址的指针。所以对函数指针进行解引用或直接调用效果是一致的。 因此上述代码两种打印方式结果相同原因就是函数指针与普通指针在语法和语义上是一致的。 4.3 两段有趣的代码 注两段代码均出⾃《C陷阱和缺陷》这本书 代码1 1 (*(void (*)())0)();让我们分析一下 (void (*)())0 意思是把0这个整数值强制类型转换成一个地址这个函数没有参数返回类型是void。 *操作符对它进行解引用得到void ()类型的匿名函数。 对这个匿名函数进行调用(),也就是调用0地址处的地址。 所以整个表达式 (void (*)())0 - 获取函数指针指向0地址 解引用函数指针得到匿名函数 () - 调用匿名函数 换句话说这个代码是 获取一个指向0地址的函数指针然后解引用它得到一个匿名函数并对这个匿名函数进行调用。 由于指针指向0地址实际调用的是内核NULL地址下的代码。这通常会触发异常或者崩溃。 所以这个代码展示了一个通过函数指针调用匿名函数的语法它实际上是在尝试访问空指针下的代码从而触发错误。 代码2 1 void (*signal(int , void(*)(int)))(int);精简理解 首先上述代码是函数声明signal是一个函数signal函数的参数有2个第一个是int类型第二个是函数指针类型该指针指向的函数参数是int返回类型是voidsignal函数的返回类型是这种类型的void(*)(int)函数指针该指针指向的函数参数是int返回类型是void 细节分析拓展如下 此时注意signal并没有与前面的*用括号结合 这个代码定义了一个signal函数它的功能是设置信号处理函数。 void(*)(int) 定义了一个函数指针该函数指针指向一个返回void,接受一个int参数的函数。 signal是函数名它有两个参数 int: 表示信号编号 void(*)(int): 函数指针表示要设置的信号处理函数 signal函数的返回值是一个函数指针void (*)(int) 这个返回值函数指针也指向一个返回void,接受一个int参数的函数。 所以整个函数声明可以解释为 signal函数用于设置信号处理函数。它接收两个参数 信号编号要设置的信号处理函数 signal函数返回原来的信号处理函数。 所以这个函数声明定义了一个典型的设置信号处理函数的接口 - signal(),它可以用来设置和获取信号的处理回调函数。 **总结来说**这个函数声明使用了嵌套的函数指针定义了signal函数的接口格式目的是为了设置和获取信号处理回调函数。 4.3.1 typedef关键字 当你看到了这里你可能在想这么长void (*signal(int , void(*)(int)))(int);的代码写出来真麻烦有没有办法可以简化他的长度呢看起来可观容易理解呢可不能自己写着写着把自己转忽悠了哈哈哈。 当然 typedef 是⽤来类型重命名的可以将复杂的类型简单化。 C语言中的typedef主要用于定义类型别名。 typedef语法 typedef 旧类型名 新类型名;例如 typedef int Int; 这行代码定义Int为int类型的别名。 typedef的主要用途 为复杂类型定义简短的名称 比如定义指针、函数指针等 typedef int (*FuncPtr)(int);隐藏实现细节 比如用结构体指针替换结构体 typedef struct {int x;int y; } Point;typedef Point* PointPtr;向下兼容 如果需要修改类型定义可以使用typedef避免修改大量代码。 提高代码可读性 给类型起个有意义的名称比如用Person替换struct Person。 标准库也广泛使用typedef 如size_t、ptrdiff_t等标准类型都是通过typedef定义的。 所以总体来说typedef主要用于为类型起别名简化和隐藏类型提高代码可读性和兼容性。它广泛应用于C标准库和程序开发中。 本小节由于篇幅有限我们先讲第一点 ⽐如我们有数组指针类型 int(*)[5] ,需要重命名为 parr_t 那可以这样写 1 typedef int(*parr_t)[5]; //新的类型名必须在*的右边函数指针类型的重命名也是⼀样的⽐如将 void(*)(int) 类型重命名为 pf_t ,就可以这样写 1 typedef void(*pfun_t)(int);//新的类型名必须在*的右边那么要简化代码2可以这样写 typedef void(*pfun_t)(int); pfun_t signal(int, pfun_t);五、函数指针数组 数组是⼀个存放相同类型数据的存储空间我们已经学习了指针数组 ⽐如 int *arr[10]; //数组的每个元素是int*那要把函数的地址存到⼀个数组中那这个数组就叫函数指针数组那函数指针的数组如何定义呢 这三个捏个才是正确的呢int (*parr1[3])(); int *parr2[3](); int (*)() parr3[3];答案是parr1 parr1 先和 [] 结合说明 parr1是数组数组的内容是什么呢 是 int (*)() 类型的函数指针。 这个定义相当于 定义一个函数指针数组parr1数组长度为3每个元素都是一个函数指针指向一个返回int,无参数的函数 这里给出一个C语言函数指针数组的简单实现示例 // 定义函数原型 int func1(void); int func2(void);int func1(void) {printf(func1 called\n);return 0; }int func2(void) {printf(func2 called\n);return 0; }int main() {// 定义函数指针数组可以存储2个函数指针int (*funcPtrArr[2])(void);// 初始化函数指针数组元素funcPtrArr[0] func1;funcPtrArr[1] func2;// 通过索引调用函数指针数组元素指向的函数funcPtrArr[0]();funcPtrArr[1]();return 0; }输出结果为 主要实现步骤 定义函数原型定义函数指针数组初始化数组元素使每个元素指向对应的函数通过数组索引调用函数指针指向的函数 这个示例演示了如何定义和使用函数指针数组来管理和调用多个函数。 实际应用中可以通过函数指针数组实现回调函数、插件等机制。函数也可以作为参数传递给其他函数。 总之函数指针数组提供了一种灵活高效的方式来管理和调用多个函数在C语言中。怎么高效下一届我们做一个计算器转移表就可以清楚理解他的巧妙之处 ⚓️总结 一、字符指针变量 字符指针变量用来存储字符串可以通过字符指针访问字符串中的每个字符。 二、数组指针变量 2.1 数组指针变量实际指向数组第一个元素的地址。 2.2 可以通过数组名直接初始化数组指针也可以通过地址运算符初始化。 三、二维数组传参的本质 二维数组传参实际上是传一级指针等同于传数组指针。 四、函数指针变量 4.1 通过函数原型声明函数指针变量类型并使用地址运算符初始化。 4.2 通过函数指针调用函数等同于使用普通函数名调用。 4.3 typedef可以简化函数指针变量类型定义。 五、函数指针数组 函数指针数组可以存储和管理多个函数指针通过数组索引调用不同函数。 总之C语言指针变量提供了一种灵活的方式来操作和管理数据如字符串、数组、函数等。指针变量的概念和使用需要熟练掌握它是C语言的重要知识点。感谢你的收看如果文章有错误可以指出我不胜感激让我们一起学习交流如果文章可以给你一个帮助可以给博主点一个小小的赞
http://www.w-s-a.com/news/170479/

相关文章:

  • 建设网站怎么判断是电脑还是手机仿租号网站源码网站开发
  • seo百度网站排名软件重庆巫山网站设计公司
  • 搭建视频播放网站网站排名诊断
  • 网站域名注册网站centos做网站服务器
  • 网站服务器共享的 vpsh5页面制作软件电脑版
  • 免费手机网站申请上海网站建设设计公司哪家好
  • 站长工具大全企业网上书店网站建设设计
  • 做网站的专业公司公司网站是做的谷歌的
  • 做网站前期工作wordpress图片并排
  • 免费注册网站哪个好wordpress评论修改
  • 合肥模板网站建设软件赤峰公司网站建设
  • 毕业设计都是做网站吗深圳网站制作企业邮箱
  • 网站排名 优帮云小规模公司简介怎么写
  • 那个做头像的网站好选择手机网站建设
  • 设计一个网站花多少时间做视频网站适合用什么服务器
  • asp网站开发环境订单系统单页面网站怎么做
  • 山东网站建设都有那些企业推广策略
  • 网站开发文档是什么概念衣服销售网站建设规划书范文
  • 中国建筑装饰网官网企业网站设计优化公司
  • 南海建设工程交易中心网站c2c交易平台有哪些?
  • 有没有专业做网站架构图的软件番禺建设网站哪个好
  • 建立网站第一步整站seo优化公司
  • php网站开发文章管理系统wordpress 评论 顶踩 心 插件
  • 网站做百度收录的意义html网页设计代码作业代码
  • 网站推广怎么做 知乎衡水做网站开发的
  • 重庆忠县网站建设报价网页构建
  • 怎么自己做单页网站怎么在阿里做网站
  • 公司网站重新备案做电商没几个能赚钱的
  • 网站开发我们都能解决怎样做网站吸引客户
  • 网站首页图片切换代码wordpress minfy