想到字符指针,我们就会突然想到,char,这里介绍一下char的使用方法
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中。
相信经过上面的解释,大家对字符指针有了一些了解。
我们再来看一个例子,来具体认识一下字符指针
#include
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; }
大家可以尽可能的猜一下结果,看看输出结果,是不是和你想的一样。
这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当
几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化
不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4不同。
顾名思义,指针数组的主语是数组,指针数组是一个存放指针的数组。
看下面这一段代码。
int* arr1[10]; //整形指针的数组
char *arr2[4]; //一级字符指针的数组
char **arr3[5];//二级字符指针的数组
例如
char* a[5];
示意图
数组指针是指针?还是数组?
答案是:指针。
我们已经熟悉:
整形指针: int * pint; 能够指向整形数据的指针。
浮点型指针: float * pf; 能够指向浮点型数据的指针。
那数组指针应该是:能够指向数组的指针。
int (*p2)[10];
/*解释:
p先和 * 结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。
这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。
*/
#include
int main()
{
int arr[10] = {0};
printf("%p\n", arr);
printf("%p\n", &arr);
return 0; }
从这可见数组名和&数组名打印的地址是一样的。
但是真的一样吗?
我们又看下面这个代码
#include
int main()
{
int arr[10] = { 0 };
printf("arr = %p\n", arr);
printf("&arr= %p\n", &arr);
printf("arr+1 = %p\n", arr+1);
printf("&arr+1= %p\n", &arr+1);
return 0; }
看下面的代码,我会对其逐一改造
void print1(int arr[10], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void test1() {
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int sz = sizeof(arr) / sizeof(arr[0]);
print1(arr, sz);
}
int main() {
test1();
}
这上面,是我们平时操作数组打印的方法
经过改造以后,就是如下的代码
void print1(int *arr, int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", *(arr+i));//通过指针来操作
}
printf("\n");
}
void test1() {
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int sz = sizeof(arr) / sizeof(arr[0]);
print1(arr, sz);
}
int main() {
test1();
}
一维数组看了,我们再来看看二维数组
void print3(int arr[3][5], int r, int c)
{
int i = 0;
for (i = 0; i < r; i++)
{
int j = 0;
for (j = 0; j < c; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
void test1() {
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
print3(arr, 3, 5);
}
int main() {
test1();
}
改造后的
void print4(int (*p)[5],int r,int c) {
int i = 0;
for (i = 0;i<r;i++) {
int j = 0;
for (j = 0;j<c;j++) {
printf("%d ",*((*p+i)+j));
}
printf("\n");
}
}
void test2() {
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
print4(arr,3,5);
}
int main() {
test2();
}
或许大家对我上面的*((*p+i)+j)的不理解,我画个示意图,大家看一下
这里有几种,我们还是举例大纲
#include
void test(int arr[])//ok?
{}
void test(int arr[10])//ok?
{}
void test(int* arr)//ok?
{}
void test2(int* arr[20])//ok?
{}
void test2(int** arr)//ok?
{}
// int** arr是不可行的
int main()
{
int arr[10] = { 0 };
int* arr2[20] = { 0 };
test(arr);
test2(arr2);
}
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);
}
#include
void print(int *p, int sz) {
int i = 0;
for(i=0; i<sz; i++)
{
printf("%d\n", *(p+i));
}
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9};
int *p = arr;
int sz = sizeof(arr)/sizeof(arr[0]);
//一级指针p,传给函数
print(p, sz);
return 0; }
#include
void test(int** ptr) {
printf("num = %d\n", **ptr);
}
int main()
{
int n = 10;
int*p = &n;
int **pp = &p;
test(pp);
test(&p);
return 0; }
函数指针的定义如下
int(*变量名)(形参表达式,形参表达式)=&函数名();
从名字上来看,就是存放函数的指针。
看下面的例子
#include
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
return 0;
}
输出结果
输出的是两个地址,这两个地址是 test 函数的地址。
数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组,
比如:
int *arr[10];
//数组的每个元素是int*
那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?
答案是:parr1
int (*parr1[10])();
int *parr2[10]();
int (*)() parr3[10];
parr1 先和 [] 结合,说明 parr1是数组,数组的内容是什么呢?
是 int (*)() 类型的函数指针。
我这里做一个例子
一种是非函数指针实现计算器
另一种是函数指针数组实现计算器
int main()
{
int input = 0;
int x = 0;
int y = 0;
int ret = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入2个操作数:>");
scanf("%d %d", &x, &y);
ret = Add(x, y);
printf("%d\n", ret);
break;
case 2:
printf("请输入2个操作数:>");
scanf("%d %d", &x, &y);
ret = Sub(x, y);
printf("%d\n", ret);
break;
case 3:
printf("请输入2个操作数:>");
scanf("%d %d", &x, &y);
ret = Mul(x, y);
printf("%d\n", ret);
break;
case 4:
printf("请输入2个操作数:>");
scanf("%d %d", &x, &y);
ret = Div(x, y);
printf("%d\n", ret);
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
}
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("***************************\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 = 0;
int y = 0;
int ret = 0;
//确立函数指针数组
int (*pfArr[])(int, int) = { 0,Add,Sub,Mul,Div };
do {
menu();
scanf("%d",&input);
if (input ==0)
{
printf("退出计算器");
break;
}
if (input>=1&& input<=4) {
printf("请输入2个操作数:>");
scanf("%d %d",&x,&y);
ret = pfArr[input](x, y);
printf("%d\n",ret);
}
else
{
printf("选择错误\n");
}
} while (input);
return 0;
}
void test(const char* str) {
printf("%s\n", str);
}
int main()
{
//函数指针pfun
void (*pfun)(const char*) = test;
//函数指针的数组pfunArr
void (*pfunArr[5])(const char* str);
pfunArr[0] = test;
//指向函数指针数组pfunArr的指针ppfunArr
void (*(*ppfunArr)[5])(const char*) = &pfunArr;
return 0;
}