目录:
1. 字符指针变量
2. 数组指针变量
3. ⼆维数组传参的本质
4. 函数指针变量
5. 函数指针数组
6. 转移表
1.字符指针变量
在指针的类型中我们知道有⼀种指针类型为字符指针 char*
这里我们有两种指针读取字符串的方式,但是第二种p2指向的是常量字符串不能修改,所以我们可以在前面添加一个const
下面我们来看一道题
#define _CRT_SECURE_NO_WARNINGS
#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;
}
那结果是什么呢?
我们创建地str1数组存储hello bit,先创建一块空间 str2数组存储hello bit又创建一块空间 ,但是这两块空间是截然不同的两块空间,而str3和str4都是指针变量,指向的是常量字符串,而常量字符串不可以改变,所以没有必要创建两份,所以创建一份还可以节省空间。
另外str1,str2,str3,str4都是创建在栈区的,而指向的hellobit.是在静态区的
2.数组指针变量
整形指针变量: int * pint; 存放的是整形变量的地址,能够指向整形数据的指针。
•浮点型指针变量: float * pf; 存放浮点型变量的地址,能够指向浮点型数据的指针。
那数组指针变量应该是:存放的应该是数组的地址,能够指向数组的指针变量。
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int a = 10;
int* p1 = &a;//整形指针
int b = 'w';
char* p2 = &b;//字符指针
int arr[10] = { 0 };
int(*p)[10] = &arr;//取出的是整个数组的地址
arr;//数组首元素的地址
int* p1[10];//p1是指针数组-存放指针的数组
int(*p2)[10];//p2是指针变量-指向的是数组,数组指针
return 0;
}
2.2 数组指针变量怎么初始化
如果要存放个数组的地址,就得存放在数组指针变量中
如果我们要用数组指针来访问数组就显得很麻烦,不建议使用
#define _CRT_SECURE_NO_WARNINGS
#include
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]);
}
return 0;
}
3. ⼆维数组传参的本质
我们很容易能利用for循环打印二维数组
#define _CRT_SECURE_NO_WARNINGS
#include
print(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");
}
}
int main()
{
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
print(arr, 3, 5);
return 0;
}
但我们有一个问题,二位数组的数组名也是首元素的地址,但是究竟是谁的地址呢?
首元素就是第一行,第一行的地址就是首元素的地址,第一行的地址就是数组指针的地址
#define _CRT_SECURE_NO_WARNINGS
#include
void print(int (*arr)[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");
}
}
int main()
{
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
print(arr, 3, 5);
return 0;
}
4. 函数指针变量
4.1 函数指针变量的创建
数组指针是指向数组的,那么函数指针是指向函数的,那么函数有没有地址呢?
我们发现函数名的地址和&函数名是一样的。
#define _CRT_SECURE_NO_WARNINGS
#include
int Add(int x, int y)
{
return x + y;
}
int main()
{
int (*pf)(int,int) = &Add;//pf是专门用来存放函数地址的,pf是函数指针变量
printf("%p\n", &Add);
printf("%p", Add);
return 0;
}
4.2 函数指针变量的使⽤
#define _CRT_SECURE_NO_WARNINGS
#include
int Add(int x, int y)
{
return x + y;
}
int main()
{
int (*pf)(int,int) = &Add;//pf是专门用来存放函数地址的,pf是函数指针变量
int c = Add(3, 5);
printf("%d\n", c);
int d = (*pf)(4, 5);
printf("%d\n", d);
int e = pf(5, 5);
printf("%d\n", e);
return 0;
}
以上这几种方法都是可以成功调用函数的
我们下面来看两个有趣的代码:
(*(void (*)())0)();
这里void(*)--函数指针类型
(void(*))--强制类型转换
(void(*)0 --将0强制转化为函数指针类型
这就意味着0处存放着无参,函数返回类型为void的类型
void (*signal(int , void(*)(int)))(int)
4.3.1 typedef关键字
typedef 是⽤来类型重命名的,可以将复杂的类型,简单化。
5. 函数指针数组
把函数的地址存到⼀个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?
#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()
{
int(*pf1)(int,int) = Add;
int(*pf2[4])(int, int) = { Add,Sub,Mul,Div };//这里pf2就是函数指针数组
int i = 0;
for (i = 0;i < 4;i++)
{
int ret = (*pf2[i])(8, 4);
printf("%d ", ret);
}
return 0;
}
完!!!