小江网站建设公司,个人网站制作代码,u9u8网站建设,怎么设计一个网页C语言指针详解#xff08;三#xff09;目录版 1、字符指针变量1.1、字符指针变量的一般应用1.2、常量字符串1.3、常量字符串与普通字符串的区别1.3.1 常量字符串的不可修改性1.3.2 常量字符串的存储 2、数组指针变量2.1、数组指针变量定义2.2、数组指针变量的初始化 3、二维… C语言指针详解三目录版 1、字符指针变量1.1、字符指针变量的一般应用1.2、常量字符串1.3、常量字符串与普通字符串的区别1.3.1 常量字符串的不可修改性1.3.2 常量字符串的存储 2、数组指针变量2.1、数组指针变量定义2.2、数组指针变量的初始化 3、二维数组传参本质4、函数指针变量4.1、函数指针变量的创建4.1.1、验证函数地址的存在4.1.2、函数指针变量表达式 4.2、函数指针变量的使用4.3、深入理解函数指针4.3.1、例题一4.3.2、例题二4.3.3、例题一解析4.3.4、例题二解析4.4、关键字 typedef 介绍4.4.1、typedef 表达式与实例演示4.4.2、define 与 typedef 的区别 5、函数指针数组6、转移表 1、字符指针变量
我们知道若指针所指向的内容是字符那么指针的类型就是字符指针类型 char* 这个指针变量就是字符指针变量。
1.1、字符指针变量的一般应用
int main()
{char ch a;char* pc ch;*pc w;printf(%c, ch);return 0;
}1.2、常量字符串
#includestdio.h
int main()
{const char* pt hello world.;//请思考这里是把一个字符串放到了 pt 指针当中了吗printf(%s\n, pt);return 0;
}
如上面代码所示的 char* name “字符串” 就是常量字符串的表达方式。那么我们思考一下注释中的问题这里是把一个字符串放到了 pt 指针当中了吗 答案是否。毕竟前面是一个指针变量其存储的应当为地址故放入的是首字符的地址。因为字符是连续存放的输出时系统会自动向后遍历直至遇到 “/0”。 运行效果图
1.3、常量字符串与普通字符串的区别
1.3.1 常量字符串的不可修改性
在 1.1 的代码和运行图中我们可见一般情况下的字符字符串是可以通过指针解引用来进行修改的。而常量字符串则不可修改如下面代码示例演示
int main()
{char* pt hello world.;printf(%s\n, pt);*pt Hello World;return 0;
}原因请见下文 1.3.2
1.3.2 常量字符串的存储
我们知道在存储位置中有栈区堆区静态区。其实在此之外还有一部分称为代码段。一般字符字符串存储在栈区中而常量字符串则存储在代码段中。所以即使通过指针解引用也不能更改字符串内容。正因如此当多个指针变量指向的常量字符串内容一致时系统不会存储多份相同的常量字符串而是会只存储一份各个变量共用这一份常量字符串即字符串地址相同。为使各位对此更加清晰我们通过以下代码和图解来进行进一步解析。
int main()
{char str1[] You are handsome !;char str2[] YOu are handsome !;char* str3 You are so beautiful;char* str4 You are so beautiful;if ( str1 str2)//数组名表示数组首元素地址{printf(str1 and str2 are same\n);}else{printf(str1 and str2 are not same\n);}if (str3 str4)//验证相同内容的常量字符串是否只有一份即验证地址是否相同{printf(str3 and str4 are same\n);}else{printf(str3 and str4 are not same\n);}return 0;
}2、数组指针变量
2.1、数组指针变量定义
数组指针顾名思义它是一种指针。我们已经熟知 整型指针变量int * p存放的是整型变量的地址指向整型数据的指针。 浮点型指针变量float * p;存放的是浮点型变量的地址指向浮点型数据的指针。 由上推知数组指针变量应当存放的是数组的地址指向数组的指针。 数组指针变量表达式int (*p) [20]; 在这个表达式中p会先和*结合表明 p 是一个指针变量然后指针指向的是一个大小为20个整型变量的数组。 注意因为 [ ] 的优先级要高于 * 号所以必须加上 来保证 p 先和 * 结合
2.2、数组指针变量的初始化
既然数组指针变量存放的是数组的地址那么我们就要将数组的地址给指针变量。数组地址数组名
int arr[10] {0};//定义数组并初始化
int (*p) [10] arr;//将数组的地址赋值给指针变量 3、二维数组传参本质
在数组章节中曾提及二维数组传参的如下写法
#include stdio.hvoid print_arr(int arr[4][5], int a, int b)
{int i 0;for (i 0; i a; i){int j 0;for (j 0; j b; j){printf(%d, arr[i][j]);}printf(\n);}
}int main()
{int arr[4][5] { {1,2,3,4,5},{2.3,4,5,6},{3,4,5,6,7},{4,5,6,7,8}};print_arr(arr, 4, 5);return 0;
}在上述代码中实参为二维数组形参也为二维数组。那么下面来介绍另一种传参方式使用数组指针进行传参。 二维数组在之前数组章节曾讲过其可以看成每个元素是一维数组的数组即二维数组的每个元素是一个一维数组二维数组首元素就是第一行是一个一维数组。 二维数组的数组名就是第一行的地址是一个一维数组的地址第一行一维数组类型为int [5]故其地址类型为int (*) [5];。如此也就证明二维数组传参实际上是传递了第一行一维数组的地址。由此可知函数形参部分也可以写成指针形式。如下所示
#include stdio.hvoid print_arr(int (*p) [5], int a, int b)//数组形参设置为数组指针
{int i 0;for (i 0; i a; i){int j 0;for (j 0; j b; j){printf(%d, *( * ( p i ) j ) );//深入理解系统对数组arr[ i ]的编译。// arr[ i ] *arr i}printf(\n);}
}int main()
{int arr[4][5] { {1,2,3,4,5},{2.3,4,5,6},{3,4,5,6,7},{4,5,6,7,8} };print_arr(arr, 4, 5);return 0;
}
4、函数指针变量
4.1、函数指针变量的创建
根据上文内容我们可以推断出函数指针变量是存储函数地址的变量同时我们可以通过函数的地址来调用函数。
4.1.1、验证函数地址的存在
下面我们来验证函数地址的存在
#includestdio.hvoid test()
{printf(hehe\n);
}int main()
{printf(test %p\n, test);//函数名printf(test %p\n, test);//取函数地址return 0;
}由此说明函数存在地址函数名与 函数名 都可以得到函数的地址。
4.1.2、函数指针变量表达式
表达式如下
int *pfint x , int y;
//或 int *pfint , int去掉变量名即为其变量类型
int *int x int 4.2、函数指针变量的使用
在使用函数指针变量调用函数时*pf与 pf两种方法都是可行的因为二者表示的意思都一致都是对应函数的地址。 代码演示
#includestdio.hint div(int a , int b)
{return a / b;
}int main()
{int (*pf) (int, int) div;printf(%d\n, (*pf)(4 , 2) );//调用方式一printf(%d\n, pf(4, 2));//调用方式二return 0;
}4.3、深入理解函数指针
4.3.1、例题一
(*( void (*)() ) 0)();//请思考此行代码的意义请思考上面代码的意义解析见 4.3.3
4.3.2、例题二
void (*signal(int, void(*)(int)))(int);//请思考此行代码的意义请思考上面代码得意义解析见 4.3.4
4.3.3、例题一解析 入手关键点在 0 处其前方应当为0的类型( void (*) () ) 0 典型的强制类型转换将0从整型 int 强制转换为函数指针类型 void ( * ) () 从而 0 就成为一个函数指针变量整体就是通过函数指针调用函数。
4.3.4、例题二解析 入手关键点在中间的函数名及其参数部分 signal(int, void(*)(int)) 我们可见在这一小部分中已经包含了signal函数的函数名和该函数内的两个参数的类型但无参数名根据C语言标准可知这应当是一个函数声明。故剩余部分为函数的返回类型为 void (*) (int)函数指针类型。因为解引用操作符 * 后要跟名称所以signal(int, void(*)(int))放在了 * 之后。综上整体为一个函数声明
4.4、关键字 typedef 介绍
4.4.1、typedef 表达式与实例演示
typedef是用来类型的重命名的可以简化复杂的类型如 4.3.4 例题二中的函数指针类型。其重定义表达式如下
typedef name1 name2;name1 表示需要重定义类型名 name2 表示 name1 重定义后的类型名
具体演示如下
#includestdio.hint div(int a , int b)
{return a / b;
}int main()
{typedef int(*son)(int, int);// * 后要跟名称所以新的类型名要放在 * 后son pf div;printf(%d\n, (*pf)(18 , 2) );printf(%d\n, pf(10, 2));return 0;
}4.4.2、define 与 typedef 的区别
1、 本质区别 #define 是预处理指令用于文本替换。在编译之前预处理器会直接将 #define 定义的宏替换成指定的文本。 typedef 是类型定义命令用于为已存在的数据类型创建一个新的名字。 2.、作用范围 #define 定义的宏没有作用域限制一旦定义就会一直有效除非被 #undef 取消定义。 typedef 定义的类型有作用域限制它遵循C语言的变量作用域规则。 3、 类型检查 #define 不进行类型检查。它仅仅是在预处理阶段进行文本替换所以不会检查替换后的类型是否正确。 typedef 会进行类型检查。当你使用 typedef 定义的新类型时编译器会检查类型是否匹配。 4、 使用方式 #define 可以用于定义常量、宏函数等不仅仅限于类型。 typedef 仅用于定义类型的别名。 5、 内存分配 #define 不会分配内存因为它只是在预处理阶段进行文本替换。 typedef 本身也不分配内存但它定义的类型在创建变量时会分配内存。
5、函数指针数组
我们知道数组是一个存储相同类型数据的存储空间。故函数指针数组就是一块连续的存储函数指针的空间。 表达式如下
type * name[number]();name 会先和 [ ] 结合表明 name 是数组数组的内容是 type (*) () 类型的函数指针。因为 * 后面要跟名称所以 * 后面跟上数组名
6、转移表
转移表是函数指针数组实例化的体现。 下面以简易计算器的改造为例
//改造前的计算器
#includestdio.hint add(int a, int b)
{return a b;
}int sub(int a, int b)
{return a - b;
}int mul(int a, int b)
{return a * b;
}int div(int a, int b)
{return a / b;
}int main()
{int x, y;int input 1;int ret 0;do{printf(**************\n);printf(1:add 2:sub\n);printf(3:mul 4:div\n);printf(0:exit \n);printf(**************\n);printf(请选择: );scanf(%d, input);switch (input){case 1:printf(请输入操作数);scanf(%d %d, x, y);ret add(x, y);printf(ret %d\n, ret);break;case 2:printf(请输入操作数);scanf(%d %d, x, y);ret sub(x, y);printf(ret %d\n, ret);break;case 3:printf(请输入操作数);scanf(%d %d, x, y);ret mul(x, y);printf(ret %d\n, ret);break;case 4:printf(请输入操作数);scanf(%d %d, x, y);ret div(x, y);printf(ret %d\n, ret);break;case 0:printf(退出程序\n);break;default:printf(选择错误\n);break;}} while (input);return 0;
}上述代码的条件分支中我们可以看到有许多重复的部分 这样就出现两个问题
1、将这样重复的代码实现成函数。 2、这个函数又能完成不同的任务
如此我们有两种思路
1、设计回调函数
2、引入函数指针数组来设计转移表。
在此我们以思路二进行改造思路一请见《C语言指针详解四》。首先我们要思考设计转移表的话函数指针数组中的元素应当如何设置。我们一共自定义了 4 个函数所以我们就把这四个函数的地址放入数组。具体演示如下
#includestdio.hint add(int a, int b)
{return a b;
}int sub(int a, int b)
{return a - b;
}int mul(int a, int b)
{return a * b;
}int div(int a, int b)
{return a / b;
}int main()
{int x, y;int input 1;int ret 0;int (*parr[5])(int , int) { 0 , add , sub , mul , div };//转移表//之所以首元素为 0 是为了便于选择使1-4都对应具体函数do{printf(**************\n);printf(1:add 2:sub\n);printf(3:mul 4:div\n);printf(0:exit \n);printf(**************\n);printf(请选择: );scanf(%d, input);if (input 4 input 1){printf(请输入操作数);scanf(%d %d, x, y);ret (parr[input])(x, y);printf(ret %d\n, ret);}else if (input 0){printf(退出计算器\n);}else{printf(输入错误);}} while (input);return 0;
}全文至此结束 写作不易不知各位老板能否给个一键三连或是一个免费的赞呢(▽)(▽)这将是对我最大的肯定与支持谢谢(▽)(▽) 文章转载自: http://www.morning.htmhl.cn.gov.cn.htmhl.cn http://www.morning.rzsxb.cn.gov.cn.rzsxb.cn http://www.morning.jhyfb.cn.gov.cn.jhyfb.cn http://www.morning.mqldj.cn.gov.cn.mqldj.cn http://www.morning.rjcqb.cn.gov.cn.rjcqb.cn http://www.morning.jxmjr.cn.gov.cn.jxmjr.cn http://www.morning.zwxfj.cn.gov.cn.zwxfj.cn http://www.morning.qyhcm.cn.gov.cn.qyhcm.cn http://www.morning.mpsnb.cn.gov.cn.mpsnb.cn http://www.morning.blxlf.cn.gov.cn.blxlf.cn http://www.morning.etsaf.com.gov.cn.etsaf.com http://www.morning.rltsx.cn.gov.cn.rltsx.cn http://www.morning.ncfky.cn.gov.cn.ncfky.cn http://www.morning.ntqqm.cn.gov.cn.ntqqm.cn http://www.morning.frqtc.cn.gov.cn.frqtc.cn http://www.morning.ktbjk.cn.gov.cn.ktbjk.cn http://www.morning.jbblf.cn.gov.cn.jbblf.cn http://www.morning.fhhry.cn.gov.cn.fhhry.cn http://www.morning.hbxnb.cn.gov.cn.hbxnb.cn http://www.morning.kxqfz.cn.gov.cn.kxqfz.cn http://www.morning.pgmyn.cn.gov.cn.pgmyn.cn http://www.morning.qlkjh.cn.gov.cn.qlkjh.cn http://www.morning.fdrwk.cn.gov.cn.fdrwk.cn http://www.morning.rmyt.cn.gov.cn.rmyt.cn http://www.morning.brrxz.cn.gov.cn.brrxz.cn http://www.morning.wqtzs.cn.gov.cn.wqtzs.cn http://www.morning.tslxr.cn.gov.cn.tslxr.cn http://www.morning.tmrjb.cn.gov.cn.tmrjb.cn http://www.morning.hlfgm.cn.gov.cn.hlfgm.cn http://www.morning.ycgrl.cn.gov.cn.ycgrl.cn http://www.morning.mmxt.cn.gov.cn.mmxt.cn http://www.morning.rgxf.cn.gov.cn.rgxf.cn http://www.morning.tkryt.cn.gov.cn.tkryt.cn http://www.morning.nrqtk.cn.gov.cn.nrqtk.cn http://www.morning.rhfh.cn.gov.cn.rhfh.cn http://www.morning.ljmbd.cn.gov.cn.ljmbd.cn http://www.morning.cniedu.com.gov.cn.cniedu.com http://www.morning.rzysq.cn.gov.cn.rzysq.cn http://www.morning.ljxps.cn.gov.cn.ljxps.cn http://www.morning.rqsr.cn.gov.cn.rqsr.cn http://www.morning.wwsgl.com.gov.cn.wwsgl.com http://www.morning.bnxnq.cn.gov.cn.bnxnq.cn http://www.morning.kltsn.cn.gov.cn.kltsn.cn http://www.morning.ylqb8.cn.gov.cn.ylqb8.cn http://www.morning.jgttx.cn.gov.cn.jgttx.cn http://www.morning.lwtfx.cn.gov.cn.lwtfx.cn http://www.morning.yxbdl.cn.gov.cn.yxbdl.cn http://www.morning.fcrw.cn.gov.cn.fcrw.cn http://www.morning.mynbc.cn.gov.cn.mynbc.cn http://www.morning.mrfr.cn.gov.cn.mrfr.cn http://www.morning.qyhcg.cn.gov.cn.qyhcg.cn http://www.morning.ffksr.cn.gov.cn.ffksr.cn http://www.morning.skkln.cn.gov.cn.skkln.cn http://www.morning.knryp.cn.gov.cn.knryp.cn http://www.morning.yzxlkj.com.gov.cn.yzxlkj.com http://www.morning.fhntj.cn.gov.cn.fhntj.cn http://www.morning.gnhsg.cn.gov.cn.gnhsg.cn http://www.morning.knczz.cn.gov.cn.knczz.cn http://www.morning.lmrjn.cn.gov.cn.lmrjn.cn http://www.morning.lxlzm.cn.gov.cn.lxlzm.cn http://www.morning.tgnwt.cn.gov.cn.tgnwt.cn http://www.morning.mwnch.cn.gov.cn.mwnch.cn http://www.morning.qfmns.cn.gov.cn.qfmns.cn http://www.morning.lqytk.cn.gov.cn.lqytk.cn http://www.morning.yrjkp.cn.gov.cn.yrjkp.cn http://www.morning.lxhny.cn.gov.cn.lxhny.cn http://www.morning.mxnrl.cn.gov.cn.mxnrl.cn http://www.morning.rdlrm.cn.gov.cn.rdlrm.cn http://www.morning.gtqx.cn.gov.cn.gtqx.cn http://www.morning.wcyr.cn.gov.cn.wcyr.cn http://www.morning.mqbzk.cn.gov.cn.mqbzk.cn http://www.morning.srxhd.cn.gov.cn.srxhd.cn http://www.morning.tzkrh.cn.gov.cn.tzkrh.cn http://www.morning.hxhrg.cn.gov.cn.hxhrg.cn http://www.morning.ygxf.cn.gov.cn.ygxf.cn http://www.morning.htbgz.cn.gov.cn.htbgz.cn http://www.morning.lhytw.cn.gov.cn.lhytw.cn http://www.morning.rmqmc.cn.gov.cn.rmqmc.cn http://www.morning.mtktn.cn.gov.cn.mtktn.cn http://www.morning.lfpdc.cn.gov.cn.lfpdc.cn