//指针进阶
1.字符指针
//字符指针char*
// 类型一
//#include
//int main(void)
//{
// char ch = 'a';
// char* p = &ch;
// printf("%c", *p);
// return 0;
//}
//类型二
//#include
//int main(void)
//{
// char* ch = "hello,word";
// //"hello,word" 该字符串相当于把第一个字母的地址放到了ch中,该字符串的值就是第一个元素的地址
// printf("%s\n", ch);
// printf("%c", *ch);
// return 0;
//}
//上述例子可以很好的证明这一点,即把这个字符串常量的首字符h的地址存放到指针变量ch中
//例题
//#include
//int main()
//{
// char str1[] = "hello";
// char str2[] = "hello";
// const char* str3 = "hello";
// const char* str4 = "hello";
// if (str1 == str2)//str1,str2为不同的char类型的数组,数组名代表首元素的地址,两个不同的数组不可能公用一块内存,则首元素地址必然不同
// printf("str1 and str2 are same\n");
// else
// printf("str1 and str2 are not same\n");
//
// if (str3 == str4)//str3,str4中均存放的是字符串hello的第一个字母h的地址,str3和str4 相同
// printf("str3 and str4 are same\n");
// else
// printf("str3 and str4 are not same\n");
//
// return 0;
//}
//指针数组
//指针数组是一个存放指针的数组
//举例如下
//#include
//int main(void)
//{
// char arr1[5] = "ABCDE";
// char arr2[5] = "BCDEF";
// char arr3[5] = "CDEFG";
// char* arr4[3] = { arr1,arr2,arr3 };
// int i, j;
// for (i = 0; i < 3; i++)
// {
// for (j = 0; j < 5; j++)
// {
//
// printf("%c", arr4[i][j]);
//
// }
// printf("\n");
// }
// return 0;
//}
//指针数组中存储的是数组的首元素地址,那么就相当于二维数组
//数组指针
//指向数组的指针,如int (*p) arr[10]
//先看一个例子
//#include
//int main(void)
//{
// char arr1[5] = "ABCDE";
// char arr2[5] = "cdefg";
// printf("%p\n", arr1);
// printf("%p\n", arr1 + 1);
// printf("%p\n", &arr1);
// printf("%p\n", &arr1 + 1);
// return 0;
//}
由此可以说明,数组名是首元素的地址,&数组名取出的是整个数组的地址(步长不同);
//数组指针的使用
//数组指针中存放的是数组的地址 一种很少用的写法
//#include
//int main(void)
//{
// int arr[10] = { 1,2,3,4,5,6,7,8 };
// int(*p)[10] = &arr;
// printf("%p\n", p);
// printf("%p", arr);
//
// return 0;
//}
//可见,数组的地址和首元素的地址的值是一样的
//数组指针的用法
//#include
//void print_arr(int(*p)[5],int x,int y)
//{
// int i, j;
// for (i = 0; i < x; i++)
// {
// for (j = 0; j < y; j++)
// {
// printf("%d", p[i][j]);
// }
// printf("\n");
// }
//}
//int main(void)
//{
// int arr[3][5] = { 1,2,3,4,5,6,7,9,10,11,23,5345 };
// print_arr(arr, 3, 5);//二维数组的数组名代表的是第一行的地址
// return 0;
//}
//回顾一下下面代码的意思
//int arr[5] 里面有5个元素的整型数组 int* p[10]里面有十个元素的指针数组 int(*p)[10]指向一个整型数组的指针
//数组参数,指针参数
//#include
//void test1(int arr[])
//{
// 正确
//}
//void test1(int arr[20])//正确
//void test1(int* arr1,int x)//正确
//
//{
// int i;
// for (i = 0; i < x; i++)
// {
// printf("%d ", arr1[i]);
// }
//
//
//}
// void test2(int *arr[20)zhengque
// void test2(int* *arr)正确
//int main(void)
//{
// int arr1[10] = {1,2,234,325353,45,345};
// //int* arr2[20] = { 0 };
// test1(arr1,10);
// //test2(arr2);
// return 0;
//}
//二维数组传参
//#include
//
//int main(void)
//{
// int arr[4][5] = { 12,23,34,4,234,2343,22,5566 };
// test(arr)
//}
//一级指针传参
//#include
//void my_print(int* p, int x)
//{
// int i;
// for (i = 0; i < x; i++)
// {
// printf("%d ", p[i]);
//
// }
//}
//
//int main(void)
//{
// int arr[10] = {12,23,34,46,534,4545,33221};
// int* p = arr;
// int sz = sizeof(arr) / sizeof(arr[0]);
// printf("%d", sz);
// my_print(p, sz);
// return 0;
//}
//二级指针
//#include
//void test(int** a)
//{
// printf("%p", **a);
//}
//int main(void)
//{
// int n = 10;
// int* p = &n;
// int** pp = &p;
// test(pp);
// test(&p);
// return 0;
//}
//void test(char** p)
//{
//
//}
//int main()
//{
// char c = 'b';
// char* pc = &c;
// char** ppc = &pc;
// char* arr[10];
// //test(&pc);//zhnegque
// //test(ppc);
// test(arr);//zhengque
// return 0;
//}
//函数指针
//#include
//void test()
//{
// printf("hehe\n");
//}
//int main()
//{
// printf("%p\n", test);
// printf("%p\n", &test);
// return 0;
//}
//由此可见,函数名和取地址函数名都是函数的地址
//那么,我们如何存放test函数的地址 void(*p)() 即可;
//函数指针数组
//数组是用来存放相同类型数据的存储空间,如果要把函数的地址存到一个数组中,这个数组就叫做函数指针数组
//int (*p[10])() 函数指针的定义
//函数指针的使用:转移表
//#define _CRT_SECURE_NO_WARNINGS
//#include
//int add(int x, int y)
//{
// return x + y;
//}
//int sub(int x, int y)
//{
// return x - y;
//}
//int mul(int x, int y)
//{
// return x * y;
//}
//int div(int x, int y)
//{
// return x / y;
//}
//int main(void)
//{
// int x,y,input,ret;
// do
// {
// printf("*********************\n");
// printf(" 1:add 2:sub \n");
// printf(" 3:mul 4:div \n");
// printf(" 0:exit \n ");
// printf("*********************\n");
// printf("请选择: \n");
// scanf("%d", &input);
// switch (input)
// {
// case 1:
// printf("请输入操作数: ");
// scanf("%d %d", &x, &y);
// ret = add(x, y);
// printf("%d", ret);
// break;
// case 2:
// printf("请输入操作数: ");
// scanf("%d %d", &x, &y);
// ret = sub(x, y);
// printf("%d", ret);
// break;
// case 3:
// printf("请输入操作数: ");
// scanf("%d %d", &x, &y);
// ret = mul(x, y);
// printf("%d", ret);
// break;
// case 4:
// printf("请输入操作数: ");
// scanf("%d %d", &x, &y);
// ret = mul(x, y);
// printf("%d", ret);
// break;
// case 0:
// printf("退出程序");
// break;
// default:
// printf("输入错误");
// break;
// }
// } while (input);
// return 0;
//}
//上述代码中有许多重复的地方,可以考虑使用转移表,简化代码
//int main(void)
//{
// int x, y, ret, input = 1;
// int (*p[5])(int x, int y) = { NULL,add,sub,mul,div };
// while (input)
// {
// printf("*********************\n");
// printf(" 1:add 2:sub \n");
// printf(" 3:mul 4:div \n");
// printf(" 0:exit \n ");
// printf("*********************\n");
// printf("请选择: \n");
// scanf("%d", &input);
// if (0 == input)
// {
// printf("退出程序");
// }
// else if (input > 0 && input < 5)
// {
// printf("输入操作数");
// scanf("%d %d", &x, &y);
// ret = (*p[input])(x, y);
// printf("%d", ret);
// }
// else
// {
// printf("输入有误");
// }
// }
// return 0;
//}