贝壳企业网站管理系统,徽与章网站建设宗旨,企业网站空间费用一年多少,多个wordpress站点互相文章目录 1. 字符指针变量剑指offer例题 2. 数组指针变量2.1 数组指针变量是什么#xff1f;2.2 数组指针变量怎么初始化 3. ⼆维数组传参的本质代码实现 4. 函数指针变量4.1 函数指针变量的创建4.3 两段有趣的代码4.3.1 typedef 关键字 5. 函数指针数组的定义 1. 字符指针变量… 文章目录 1. 字符指针变量剑指offer例题 2. 数组指针变量2.1 数组指针变量是什么2.2 数组指针变量怎么初始化 3. ⼆维数组传参的本质代码实现 4. 函数指针变量4.1 函数指针变量的创建4.3 两段有趣的代码4.3.1 typedef 关键字 5. 函数指针数组的定义 1. 字符指针变量
在指针的类型中有一种指针类型叫字符指针char* 简单代码如下:
int main()
{char ch w;char *pc ch;*pc w;return 0;
}再看如下代码: int main(){const char* pstr hello bit.;printf(%s\n, pstr);return 0;}这里是把⼀个字符串(hello bit.)放到指针变量里了吗 其实本质是把字符串hello bit 首字符的地址放到了pstr中(pstr指向字符串的首字符的地址)。
剑指offer例题
下面我们一起来欣赏下这道剑指发的题目
#include stdio.hint 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;
}a.首先我们要清楚创建数组名str1为其开辟了一块空间str2也等同开辟了一块空间显然二者的地址并不相同。 我们又知道数组名比较的是首元素的地址因此str1 ! str2。
b.字符串“hello bit.”向内存申请了一块空间指针str3指向了字符串的首元素的地址str4也是指向字符串首元素的地址。 由于hello bit.的地址并不发生变化即str3和str4都是指向同一个地址那么str3 str4。 2. 数组指针变量
2.1 数组指针变量是什么
前面我们学习了指针数组指针数组是⼀种数组数组中存放的是地址指针。
数组指针变量是指针变量还是数组 答案是指针变量。(存放的应该是数组的地址能够指向数组的指针变量。) int (*p)[10];p先和*结合说明p是⼀个指针变量然后指针指向的是⼀个⼤小为10个整型的数组。所以p是 ⼀个指针指向⼀个数组叫数组指针。由于[]的优先级高于*故要用()保证*和p集合
2.2 数组指针变量怎么初始化
数组指针变量是⽤来存放数组地址的那怎么获得数组的地址呢
int arr[10] {0};
arr;//得到的就是数组的地址3. ⼆维数组传参的本质
前言有⼀个⼆维数组的需要传参给⼀个函数的时候是这样写的。
#includestdio.hvoid print(int arr[][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 };print(arr, 3, 5);return 0;
}那么我们是否可以通过指针的方式实现二维数组的传参呢 答案是肯定的。 首先我们先来回忆下一维数组如何进行传参。
我们再来理解下二维数组⼆维数组其实可以看做是每个元素是⼀维数组的数组也就是⼆维 数组的每个元素是⼀个⼀维数组。那么⼆维数组的⾸元素就是第⼀⾏是个⼀维数组。 所以根据⼆维数组的数组名表示的就是第⼀行的地址那就意味着⼆维数组传参本质上也是传递了地址传递的是第⼀行这个⼀维数组的地址。
代码实现
void print(int (*p)[][5], int r, int c)
{int i 0;for (i 0;i r;i){int j 0;for (;j c;j){//这段也可以写成printf(%d, *(*(pi)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 };print(arr, 3, 5);return 0;
}4. 函数指针变量
4.1 函数指针变量的创建
学习完数组指针后根据类比关系我们不难得出结论 函数指针变量应该是⽤来存放函数地址的未来通过地址能够调⽤函数的。 那么我们该如何知道函数是否有地址呢
int Add(int x, int y)
{return x y;
}int main()
{//二者是等价的printf(%p\n, Add);printf(%p\n, Add);return 0;
}可以发现函数名就是函数的地址。 那么有什么办法能将函数地址存起来呢 仿效数组指针的方式那肯定有函数指针变量将函数地址存起来且此形式和数组指针类似。 通过函数指针变量的方式完成对应操作 #includestdio.hint Add(int x, int y)
{return x y;
}int main()
{int (*pf)(int, int) Add; //pf函数指针变量int ret (*pf)(2, 3);//int ret (pf)(2, 3);printf(%d\n, ret);return 0;
}4.3 两段有趣的代码
《C陷阱和缺陷》有这样两个代码
(*(void (*)())0)();void (*signal(int , void(*)(int)))(int);
我们先来解读第一段代码
int main()
{( * ( void (*)() ) 0 ) ();return 0;
}我们先从0着手 1.将0强制类型转换成void(*) () 这种类型的函数指针这个函数没有参数返回类型是void. 2.然后去调用()地址处的函数.
第二段代码
4.3.1 typedef 关键字
typedef 是⽤来类型重命名的可以将复杂的类型简单化。
例若你觉得unsigned int 写起来不方便
typedef unsigned int uint;那数组指针重命名又是咋样的呢
typedef int(*parr_t)[5]新的命名并不是写在最右边而应该写在()里边。
同理函数指针重命名也是如此
typedef void(*pfun_t)(int);了解了typedef关键字后我们清楚了它的作用是化繁为简(缺点旁人并不能明白这个代码是啥类型因此在旁边加上注释更有利于理解)。 我们可以将上面两段有趣的代码进行简化:
1. typedef void(*pfun_t)(int);2. pfun_t signal(int, pfun_t);5. 函数指针数组的定义
上一节我们学习了指针的概念及使用那么是否有一种方式能将函数的地址存放到数组中呢 这个数组就叫函数指针数组那函数指针的数组如何定义呢
int (*parr1[3])();parr1先和[]结合说明parr1是一个数组其指向的内容是int (*)()类型的函数指针。 下一节会详细讲解函数指针数组的应用内容(明白其重要性)。