hellow 大家好久不见了,最近一直在忙着期末考试,博客也好久没写了,这几天花了一些时间把鹏哥c语言指针的进阶看完,我就打算用两篇文章浅浅的总结一下指针进阶中我们要学的一些基础知识,也希望大家能指出文章中的不足。
目录
1 字符指针
2 指针数组 and 数组指针
3 数组参数 and 指针参数
3.1 一维数组传参
3.2 二维数组传参
3.3 一级指针传参
3.4 二级指针传参
4 函数指针数组
1 字符指针
相信大家对一些基本的字符指针常识已经有所了解,这里便不再多说。那么下面的代码你能够理解吗?
#define _CRT_SECURE_NO_WARNINGS 1 #includeint main() { const char* pc = "hellow world";//这里是把整个字符串放在pc里了吗? return 0; }
答案显然不是,这里的pc存放的是常量字符串首元素的地址,也就是h的地址。有了这个认识,那我们来看接下来的代码
#includeint 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 samen"); else printf("str1 and str2 are not samen"); if(str3 ==str4) printf("str3 and str4 are samen"); else printf("str3 and str4 are not samen"); return 0; }
那么结果究竟是什么呢?
我们在vs中运行一下:
这里可以明显的看出来str1与str2不相等,str3与str4相等。str1与str2是两个不同的字符数组,尽管它们存放的内容是相同的,但是它们的地址却是不相同的。而"hellow bit"这个常量字符串系统给它开辟空间时只开辟了11个字节大小的空间给它 ,当有两个指针共同指向相同字符串首元素地址时不会额外再给其中一个指针分配内存,所以str3和str4是一回事,这也就很好的解释了为什么前面会有const修饰。
2 指针数组 and 数组指针
下面的哪个是指针数组?哪个是数组指针你能够分清吗?
int* p1[10];
int (*p2)[10];
由于[]的优先级大于*的优先级,所以很容易就能够判断出p1是指针数组,p2是数组指针
那么来点稍微有点难度的,下面的parr1又是什么意思呢?
int (*parr1[10])[5];
由于[]的优先级大于*,我们可以知道parr1是一个数组,数组里有10个元素,每个元素的类型是int (*)[5] ,也就是一个数组指针,该指针指向的数组有5个元素,每个元素的类型是int.
3 数组参数 and 指针参数 3.1 一维数组传参 #include
上面这几种传参方式都是没有问题的,也很容易理解
3.2 二维数组传参 void test(int arr[3][5])//ok? {} void test(int arr[][])//ok? // 不行 {} void test(int arr[][5])//ok? {} //总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。 //因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。 //这样才方便运算。 void test(int *arr)//ok? // 不行 {} void test(int* arr[5])//ok? // 不行 {} void test(int (*arr)[5])//ok? {} void test(int **arr)//ok? // 不行 {} int main() { int arr[3][5] = {0}; test(arr); } 3.3 一级指针传参 #include4 函数指针数组 数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组, 比如:
int *arr[10]; //数组的每个元素是int*
那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?
int (*parr1[10])(); int *parr2[10](); int (*)() parr3[10];答案是:parr1 parr1 先和 [] 结合,说明 parr1是数组,数组的内容是什么呢? 是 int (*)() 类型的函数指针。 函数指针数组的用途: 转移表 例子:(计算器) 用普通的方法实现:
#includeint 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( "*************************n" ); printf( "请选择:" ); scanf( "%d", &input); switch (input) { case 1: printf( "输入操作数:" ); scanf( "%d %d", &x, &y); ret = add(x, y); printf( "ret = %dn", ret); break; case 2: printf( "输入操作数:" ); scanf( "%d %d", &x, &y); ret = sub(x, y); printf( "ret = %dn", ret); break; case 3: printf( "输入操作数:" ); scanf( "%d %d", &x, &y); ret = mul(x, y); printf( "ret = %dn", ret); break; case 4: printf( "输入操作数:" ); scanf( "%d %d", &x, &y); ret = div(x, y); printf( "ret = %dn", ret); break; case 0: printf("退出程序n"); breark; default: printf( "选择错误n" ); break; } } while (input); return 0;
这样实现很容易理解,也是我们很容易想到的一种方式,但是坏处也很明显,就是有些语句反复出现,使代码显得很冗余(用回调函数可以简化代码,这里就不在多说)。另外,我们如果想要增加一些计算方法的话,添加的代码仍然很冗余,这样我们就可以用函数指针数组来解决问题。
代码如下:
#includeint 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(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表 while (input) { printf( "*************************n" ); printf( " 1:add 2:sub n" ); printf( " 3:mul 4:div n" ); printf( "*************************n" ); printf( "请选择:" ); scanf( "%d", &input); if ((input <= 4 && input >= 1)) { printf( "输入操作数:" ); scanf( "%d %d", &x, &y); ret = (*p[input])(x, y); } else printf( "输入有误n" ); printf( "ret = %dn", ret); } return 0; }
好啦,指针的进阶(上)我就先分享到这里了,(下)我会在这两天整理出来,也希望大家多多支持!



