目录
1.字符指针变量
顾名思义,字符指针也就是char*,在使用中,一般简单的使用可以这样
#include<stdio.h>
int main()
{
char ch = 'w';
char* p = &ch;
return 0;
}
那如果是字符串,那就可以这样
#include<stdio.h>
int main()
{
char ch[] = "abcdef";
char* p = ch;
*p = 'w';
printf("%s ", p);
return 0;
}
这里的首字符成功的被‘w'所替换掉了;那吧字符串直接存入指针里面,又是什么效果呢?
#include<stdio.h>
int main()
{
/*char ch[] = "abcdef";
char* p = ch;*/
char* p = "abcdef";
*p = 'w';
printf("%s ", p);
return 0;
}
发现运行结果什么都没有。实际上在第二段代码中(char ch[] = "abcdef"; char* p = ch;)是将字符串首元素地址存入了指针变量p中,且数组内容是可以更改的。而在第三段代码中(char* p = "abcdef";)也同样只是存入了字符串首元素的地址,而不是整个字符串的地址,且字符串内容是无法修改的,即(*p='w';是错误的);
两种表达方式,指针均是指向字符串首字符的,因为是连续存放,所以能访问到所有元素;因为第二种写法,字符串内容不可修改,所以更好的写法是在*前面加const(const char * p="abcdef";),以便来提醒我们,内容不可改。
注:%s打印地址只用提供首元素地址。
《剑指offer》中有这样一道题
#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;
}
2.数组指针变量
指针数组,指针数组是⼀种数组,数组中存放的是地址(指针);顾名思义,数组指针,是一种指针,是指向数组的指针。
2.1定义
数组指针变量的定义是这样的
int (*p)[10];
p先和*结合,说明p是⼀个指针变量变量,然后指着指向的是⼀个大小为10个整型的数组。所以 p是⼀个指针,指向⼀个数组,叫 数组指针。 这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。
2.2存放
如果要存放数组的地址,那就得用数组指针变量
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
int(*p)[10] = &arr;
return 0;
}
其中,int是p指向的数组的元素类型,p是数组指针变量名,[10]是p指向数组的元素个数。
3.二维数组传参的本质
先看这样一个代码
#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;
}
这里函数test用二维数组来接收主函数传来的二维数组,是可行的。实际上,二维数组在储存的时候并不是我们直观的用横和列来排列组合的,而是二维数组里的每个元素是⼀维数组的数组,也就是⼆维数组的每个元素是⼀个⼀维数组。那么⼆维数组的首元素就是第⼀行,是个⼀维数组。
所有我们结合数组名的规则(数组名是数组首元素的地址),二维数组的数组名表示的就是第⼀行的地址,是一维数组的地址。那么二维数组arr[3][5]的首元素就是第一行数组,即arr[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;
}
4.函数指针变量
函数指针变量应该是用来存放函数地址的,希望通过地址能够调用函数的。
之前提到过,“&数组名”,是数组的地址,而“数组名”是数组首元素的地址;在函数指针中,无论是“&函数名”还是“函数名”均是指函数的地址。
4.1创建
如果要将函数的地址存放起来,就得创建函数指针变量,函数指针变量的写法其实和数组指针非常类似。
//代码1
void test()
{
printf("hehe\n");
}
void (*pf1)() = &test;
void (*pf2)()= test;//&test和test一样
//代码2
int Add(int x, int y)
{
return x+y;
}
int(*pf3)(int, int) = Add;
int(*pf3)(int x, int y) = &Add;//x和y写上或者省略都是可以的
4.2使用
#include<stdio.h>
int add(int x, int y)
{
return x+y;
}
int main()
{
int (*pf)(int, int) = &add;
int a = add(2, 3);//函数名调用
printf("%d\n", a);
int b = (*pf)(2, 3);//函数指针调用
printf("%d\n", b);
int c = pf(2, 3);//函数指针调用
printf("%d\n", c);
return 0;
}
由此我们也可以发,在调用函数指针的时候,*可以省略,就像上面代码(int b = (*pf)(2, 3);)和(int b = pf(2, 3);)是等价的
5.typedef关键字
typedef是用来类型重命名的,可以将复杂的类型,简单化。例如
typedef unsigned int uint;//将unsigned int 重命名为uint
unsigned int a;
uint a;//重命名后,两者等价
如果是指针类型也同样可以重命名,例如
typedef int* ptr_t;//将int*重命名为ptr_t
int* p;
ptr_t p;//重命名后,二者等价
但是对于数组指针和函数指针稍微有点区别:
比如我们有数组指针类型 int(*)[5] ,需要重命名为 parr_t ,那可以这样写:
typedef int(*parr_t)[5]; //新的类型名必须在*的右边
int (*p)[5];
parr_t p;//重命名后,二者等价
比如将函数指针类型将 void(*)(int) 类型重命名为 pfun_t ,就可以这样写:
typedef void(*pfun_t)(int);//新的类型名必须在*的右边
void(*pa)(int);
pfun_t pa;//重命名后,二者等价
6.函数指针数组
要把函数的地址存到⼀个数组中,那这个数组就叫函数指针数组,怎么定义呢
int (*parr1[3])();
parr1 先和 [ ] 结合,说明 parr1是数组;将parr1[3]去掉剩余的int (*)() ,是说明这是int (*)()类型的函数指针
接下来就是函数指针数组的使用了
//计算两个整数的加减乘除
#include<stdio.h>
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()
{
int (*fparr[4])(int, int) = { add,sub,mul,div };
int i = 0;
for (i = 0; i < 4; i++)
{
int r = fparr[i](8, 4);
printf("%d\n", r);
}
return 0;
}
6.1转移表
函数指针数组还有一个应用就是,转移表。
举例:计算器的⼀般实现:
#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;
}
如果还觉得麻烦,还可以这样
#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;
}
void menu()
{
printf("*************************\n");
printf(" 1:add 2:sub \n");
printf(" 3:mul 4:div \n");
printf(" 0:exit \n");
printf("*************************\n");
}
void calc(int (*pf)(int, int))
{
int x = 0;
int y = 0;
int ret = 0;
printf("输入操作数:");
scanf("%d %d", &x, &y);
ret = add(x, y);
printf("ret = %d\n", ret);
}
int main()
{
int input = 1;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
calc(add);
break;
case 2:
calc(sub);
break;
case 3:
calc(mul);
break;
case 4:
calc(div);
break;
case 0:
printf("退出程序\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
标签:return,int,ret,学习,数组,printf,指针
From: https://blog.csdn.net/2401_85711575/article/details/141246765