目录
概念
1.内存中最小单元(一个字节)的编号,也就是地址。即:编号——地址——指针
*我们平常口语所说的指针其实是指针变量,即用来存放指针(地址)的变量
指针类型
相同点
不同类型的指针所占用空间大小是一样的
由此我们可以做一些强制类型转换
不同点
1.解引用时访问权限不同
a的初始地址和值:
int*指针将其修改为0:
char*指针将值修改为0
可以看出,指针类型决定了其解引用时的访问权限
2.给指针+1时地址不同
b+n=b+sizeof(int)*n
c+n=c+sizeof(char)*n
*指针类型决定了其走一步的距离
指针关系运算
条件
1.类型一致
2.指向同一块空间
二级指针
概念:存放指针变量地址的指针
a的地址存放在ap中,ap的指针存放在app中,ap是一级指针,app是二级指针
指针与数组
指针名和取地址指针名
对数组arr执行以下三种操作
1:printf("%p",arr);
2:printf("%p",&arr);
3: printf("%p",&arr[0]);
他们的值都是arr的首元素arr[0]的地址
数组名在绝大多数情况下都表示首元素地址,但是有俩种情况除外:
1:sizeof(数组名);此时数组名表示整个数组,计算得到数组的总大小
2:&数组名;这里数组名表示整个数组,从地址角度来说和首元素地址的值一样,但是意义不一样:
对于&arr,因为它表示这个数组,所以对它加一,它跨过这个数组的大小即4*5=20;
用指针访问数组
int arr[5]={0};
for(int i=0;i<5;i++)
{
printf("%d",*(arr+i));
}
for(int j=0;j<5;j++)
{
printf("%d",arr[j]);
}
俩种方式本质上差不多:
1:取得首元素地址
2:给地址加i
3: arr+i进行解引用,取得对应的值,即arr[i]=*(arr+i)
由此,我们可以推理出
arr[i]=i[arr]=*(arr+i)
指针数组
概念:存放指针的数组
由此,我们可以得到一种二维数组的表达方式
ptr[i][j]=*(*(ptr+i)+j)
数组指针
数组指针本质上还是一个指针,和int*,char*一样,数组指针是一个指向数组的指针
int a[5]={0};
int (*p)[5]=&a;
应用:二维数组的首元素是其第一行,所以二维数组的数组名就表示其第一行的地址,这时就需要用到数组指针
函数指针
1.函数的地址就是它的函数名
2.函数名和&函数名意义一样都是函数地址
3.形式:返回类型 (*指针名)(参数类型)=函数名;
int add(int x,int y)
{
}
int (*p)(int ,int)=add;//add为一个函数名
//调用
int a=p(3,5);//*号可以省略
函数指针数组
存放函数指针的数组 - 函数指针数组
形式:返回类型 (*指针名[元素数量])(参数类型)={数组中存放的函数名};
函数指针数组的调用
形式:返回类型 接收返回值变量名=指针名[调用函数在数组中的位置](参数)
应用举例:简单计算器
#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 }; //转移表
while (input)
{
printf( "*************************\n" );
printf( " 1:add 2:sub \n" );
printf( " 3:mul 4:div \n" );
printf( "*************************\n" );
printf( "请选择:" );
scanf( "%d", &input);
if ((input <= 4 && input >= 1))
{
printf( "输入操作数:" );
scanf( "%d %d", &x, &y);
ret = (*p[input])(x, y);
}
else
printf( "输入有误\n" );
printf( "ret = %d\n", ret);
}
return 0;
}