扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
目录
创新互联是一家集网站建设,江北企业网站建设,江北品牌网站建设,网站定制,江北网站建设报价,网络营销,网络优化,江北网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。1.字符指针
2.指针数组
3.数组指针
4.指针参数
5.函数指针
6.函数指针数组
6.1模拟加减乘除计算器
6.2指向函数指针数组的指针
1.字符指针
int main()
{
const char* p = "abcdefg";
//*p = 'hijklmn';
printf("%s ", p);
printf("%c\n", *p);
return 0;
}
这里的p是一个字符指针,指向字符串首字母的地址,加上const后无法修改,更加严谨。
结果为 abcdefg a
那字符指针和字符串以及字符数组有什么区别呢?来道改编的面试题看看叭~
int main()
{
char str1[] = "hello world.";
char str2[] = "hello world.";
const char* str3 = "hello world.";
const char* str4 = "hello world.";
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;
}
str1 和 str2 是两个不同的数组,相同的常量字符串去初始化不同的数组的时候会开辟出不同的内存块,各自独立占用一块空间;str3 和 str4 指向同一个常量字符(无法改变),当几个指针指向同一个字符串的时候,实际会指向同一块内存。
再来看这道面试题,str1 和 str2 都指向的是数组首元素的地址,内存开辟的空间不同,数组首元素的地址肯定不同,所以 str1 != str2 ;而 str3 和 str4 指向的是同一块内存,所以 str3 == str4。
2.指针数组不同于一维数组和二维数组,指针数组中各个元素之间地址不是连续的。
int* arr1[10]; //一级整形指针的数组
char *arr2[10]; //一级字符指针的数组
char **arr[10]; //二级字符指针的数组
先来两个例子练练手:
int main()
{
//加const更严谨,不加也可
const char* arr[4] = { "abc","def","ghi","jkl" };
int i = 0;
for (i = 0; i< 4; i++)
{
printf("%s\n", arr[i]);
}
return 0;
}
int main()
{
int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 2,3,4,5,6 };
int arr3[5] = { 3,4,5,6,7 };
int* arr[3] = { arr1,arr2,arr3 };
int i, j;
for (i = 0; i< 3; i++)
{
for (j = 0; j< 5; j++)
{
printf("%d\n", arr[i][j]);//这里与二维数组很像
} //*(arr[i]+j)或*(*(arr+i)+j)也可
printf("\n");
}
return 0;
}
3.数组指针数组指针——存放数组地址的指针——指向数组的指针
格式:int (*p)[10] = &arr; 其中 *p 相当于 arrarr 只是首元素的地址,&arr 取出的是数组的地址,只有数组的地址需要数组来接收;p 先和 * 结合,说明 p 是一个指针变量,指向一个大小为10个的 int 型的数组。
注意:[ ]的优先级高于 * ,所以必须加上()来保证 p 先和 * 结合。
//一维
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;
int i = 0;
for (i = 0; i< 10; i++)
{
printf("%d ", (*p)[i]);
} //*p相当于arr,即arr[i]
return 0;
}
//二维
void Print(int(*p)[4], int row, int col)
{ //指向第一行的四个元素
int i, j;
for (i = 0; i< row; i++)
{
for (j = 0; j< col; j++)
{
printf("%d", (*(p + i))[j]);
} //p[i][j]也可
printf("\n");
}
}
int main()
{
int arr[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
Print(arr, 3, 4);//二维数组名是第一行的地址
return 0;
}
int arr[10] | 整形数组,数组里有10个 int 类型的元素 |
int *parr1[10] | 指针数组,数组里有10个 int* 类型的元素 |
int (*parr2)[10] | 数组指针,指向一个有10个 int 类型元素的数组, |
int (*parr3[10])[5] | 数组指针数组,parr3是有10个 int(*)[5]的数组指针类型元素的数组 |
//一级指针传参
void test(int* p)
{
;
}
int main()
{
int n = 10;
int* p = &n;
int arr[10];
test(&n);//ok
test(p);//ok
test(arr);//ok
return 0;
}
//二级指针传参
void test(int** p)
{
;
}
int main()
{
int n = 10;
int* p = &n;
int** pp = &p;
int* arr[10];
test(&p);//ok
test(pp);//ok
test(arr);//ok
return 0;
}
这里真的是很懵,还是要多加练习啊!!
5.函数指针函数指针——指向函数的指针
格式:int (*pf)(int, int) = &Add;
与数组不同,&函数名 和 函数名 都是函数的地址。
int Add(int x, int y)
{
return x + y;
}
int main()
{
printf("Add的地址为:%p\n", &Add);
int (*pf)(int, int) = &Add;//pf为函数指针,存放函数地址
//&Add 等价于 Add
int ret1 = Add(2, 3);
int ret2 = (*pf)(2, 3);//*pf = Add
int ret3 = pf(2, 3);//pf = Add
int ret4 = (******pf)(2, 3);//*只是个摆设,无论前面有多少个*程序都不会用
printf("%d %d %d %d\n", ret1, ret2, ret3, ret4);
return 0;
}
6.函数指针数组6.1模拟加减乘除计算器字符指针数组:char* arr1[10];
整型指针数组:int* arr2[10];
函数指针数组:int (*arr3[5]) (int , int);
int (*pf[5])(const char*) = {&Add};
#define _CRT_SECURE_NO_WARNINGS
#include//用宏定义更加简便
//#define Add(x,y) (x+y)
//#define Sub(x,y) (x-y)
//#define Mul(x,y) (x*y)
//#define Div(x,y) (x/y)
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;
}
void menu()
{
printf("********** Ji Suan Qi **********\n");
printf("********************************\n");
printf("******* 1.add 2.sub *******\n");
printf("******* 3.mul 4.div *******\n");
printf("******* 0.exit *******\n");
printf("********************************\n");
}
int main()
{
int input = 0;
int x, y;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入两个数:");
scanf("%d%d", &x, &y);
printf("%d\n", Add(x, y));
break;
case 2:
printf("请输入两个数:");
scanf("%d%d", &x, &y);
printf("%d\n", Sub(x, y));
break;
case 3:
printf("请输入两个数:");
scanf("%d%d", &x, &y);
printf("%d\n", Mul(x, y));
break;
case 4:
printf("请输入两个数:");
scanf("%d%d", &x, &y);
printf("%d\n", Div(x, y));
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
我们发现,这样写虽然逻辑清晰,但过程太过繁杂,而且不论是函数还是case语句格式相通,既然这样,不妨试一试函数指针数组,看看能否简化程序。
#define _CRT_SECURE_NO_WARNINGS
#includeint 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;
}
void menu()
{
printf("********** Ji Suan Qi **********\n");
printf("********************************\n");
printf("******* 1.add 2.sub *******\n");
printf("******* 3.mul 4.div *******\n");
printf("******* 0.exit *******\n");
printf("********************************\n");
}
int(*pf[5])(int, int) = { 0,Add,Sub,Mul,Div };//第一个元素放0是为了让后面元素下表对应菜单选项
int main()
{
int input = 0;
int x, y;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
if (input == 0)
{
printf("退出计算器\n");
break;
}
else if (input >= 1 && input<= 4)
{
printf("请输入两个数:");
scanf("%d%d", &x, &y);
int ret = pf[input](x, y);//!!!
printf("%d\n", ret);
}
else
printf("输入错误\n");
} while (input);
return 0;
}
答案是肯定的,使用函数指针数组后case语句可以省略,代码的可读性更强。
6.2指向函数指针数组的指针(无限套娃 o.O ……)
函数指针数组:int (*pf[5])(int,int);
指向函数指针数组的指针:int ( * ( *ppf ) [5] ) ( int , int ) = &pf;
看变量类型: 把变量名去掉;看数组中元素的类型:把()里*之后的部分去掉。
难哇,学啊!
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流