赞
踩
目录
- int main()
- {
- char ch = 'w';
- char *pc = &ch;//一般使用方式
- *pc = 'w';
- return 0;
- }
-
- int main()
- {
- const char* pstr = "hello bit.";//这里是把一个字符串放到pstr指针变量里了吗?
- printf("%s\n", pstr);
- return 0;
- }
代码const char* pstr = "hello bit."; 不是把字符串 hello bit 放到字符指针 pstr 里,而是把字符串hello bit.的首字符的地址放到了pstr中
我们通过一道例题加深理解
- #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");
- 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;
- }
所以数组指针变量:存放的应该是数组的地址,能够指向数组的指针变量
- int *p1[10];
- int (*p2)[10];
*
)。换句话说,p1是一个数组,可以存储10个地址,每个地址都指向一个 int 类型的值。这个数组可以用来存储指向不同 int 变量的指针,或者指向 int 数组首元素的指针。数组指针变量:
int (*p)[10];
- int arr[10] = {0};
- &arr;//得到的就是数组的地址
-
- int(*p)[10] = &arr;//数组指针变量
- int (*p) [10] = &arr;// &arr 和 p 的类型相同
- | | |
- | | |
- | | p指向数组的元素个数
- | p是数组指针变量名
- 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;
- }
实参是二维数组,形参也写成二维数组的形式,其实,二维数组起始可以看做是每个元素是一维数组的数组,也就是二维数组的每个元素是一个一维数组。那么二维数组的首元素就是第一行,是个一维数组
根据数组名是数组首元素的地址,二维数组的数组名表示的就是第一行的地址,是一维数组的地址。根据上面的例子,第一行的一维数组的类型就是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;
- }
总结:二维数组传参,形参的部分可以写成数组,也可以写成指针形式
函数指针变量应该是用来存放函数地址的,并通过地址能够调用函数
- #include <stdio.h>
-
- void test()
- {
- printf("hehe\n");
- }
-
- int main()
- {
- printf("test: %p\n", test);//函数是否有地址
- printf("&test: %p\n", &test);
- return 0;
- }
函数有地址并且 test 和 &test 相同
函数指针类型解析:
- int (*pf3) (int x, int y)
- | | ------------
- | | |
- | | pf3指向函数的参数类型和个数的交代
- | 函数指针变量名
- pf3指向函数的返回类型
-
- int (*) (int x, int y) //pf3函数指针变量的类型
- void test()
- {
- printf("hehe\n");
- }
-
- void (*pf1)() = &test;
- void (*pf2)()= test;
-
- int Add(int x, int y)
- {
- return x+y;
- }
-
- int(*pf3)(int, int) = Add;
- int(*pf3)(int x, int y) = &Add;//x和y写上或者省略都是可以的
- //通过函数指针调用指针指向的函数
- #include <stdio.h>
-
- int Add(int x, int y)
- {
- return x+y;
- }
-
- int main()
- {
- int(*pf3)(int, int) = Add;
- printf("%d\n", (*pf3)(2, 3));//5
- printf("%d\n", pf3(3, 5));//8
- return 0;
- }
- //代码1
- (*(void (*)())0)();
-
-
- ( )0//强制类型转换
- (void (*)())0//函数指针 返回值为void 参数为void
- ( *(void (*)())0 )
- ( *(void (*)())0 ) ();//调用地址为 0 的函数
- //代码2
- void (*signal(int , void(*)(int)))(int);
-
- void(*)(int)//函数指针 返回值为void 参数为int
- signal(int , void(*)(int))//signal 函数返回值为void 参数为int
- void (*signal)(int);
typedef 是用来类型重命名
- //将unsigned int 重命名为uint
- typedef unsigned int uint;
-
- //将int* 重命名为ptr_t
- typedef int* ptr_t;
-
- //数组指针类型int(*)[5]重命名为parr_t
- typedef int(*parr_t)[5]; //新的类型名必须在*的右边
-
- //void(*)(int) 类型重命名为pf_t
- typedef void(*pfun_t)(int);//新的类型名必须在*的右边
简化代码2,可以这样写
- typedef void(*pfun_t)(int);
-
- pfun_t signal(int, pfun_t);
函数的地址存到一个数组
int (*parr1[3])();
int (*)() 类型的函数指针
计算器的一般实现:
- #include <stdio.h>
- int 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;
- }
通过函数指针数组的实现后:
- #include <stdio.h>
-
- int 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 }; //转移表
- 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 = (*p[input])(x, y);
- printf( "ret = %d\n", ret);
- }
- else if(input == 0)
- {
- printf("退出计算器\n");
- }
- else
- {
- printf( "输入有误\n" );
- }
- }while (input);
- return 0;
- }
谢谢观看
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。