数组与指针
数组名的理解
根据以前学的知识取数组arr首元素的地址一般会用&arr[0],接下来我们来看一段代码
由上图可知&arr[0]和arr的结果一样,所以可以知道数组名就是数组首元素的地址。
那数组名都是代表数组首元素的地址吗?有没有特例呢?
下面举出特例:
·int sz=sizeof(arr);//sizeof中单独放数组名时,这里的数组名表示整个数组,用来计算数组大小
·int *p=&arr; //这里的数组表示整个数组,取出的是整个数组的地址
用指针访问数组
int arr[5]={1,2,3,4,5};
int *p=arr;
for(int i=0;i<5;i++)
printf("%d ",*(p+i));//这里的*(p+i)等价p[i],感兴趣的可以去试试
二级指针
指针变量也是变量,是变量就存在地址,那么指针变量的地址存放在哪里呢。在C语言中称为二级指针。(二级指针的地址存放在三级指针中……以此类推)
int a=10;
int *p1=&a;
int **p2=&p1;
指针数组
由存放整形的数组称为整型的数组,存放字符的数组称为字符数组,可以得出指针数组是存放指针的数组。(下面来用图来直观的表示)
int main()
{
int arr1[3]={1,2,3};
int arr2[3]={4,5,6}; arr内部展示
int arr3[3]={7,8,9}; 1 2 3
int *arr[3]={arr1,arr2,arr3}; arr 4 5 6
for(int i=0;i<3;i++) 7 8 9
{
for(int j=0;j<3;j++)
printf("%d",arr[i][j]);
putchar('\n');
}
}
注意:指针数组只是模拟二维数组,不是真正的二维数组
指针变量的类型
字符指针变量
字符指针(char *)
char ch='m';
char* p=&ch;
理解完字符指针后,接下来我们来看一段代码
const char *str="hello world"
这里是把字符串"hello world"的地址放到指针变量str里了吗?显然是不可能的。
这里的存放类似于数组,只是把字符串首字符h的地址放到字符指针str里了。
数组指针变量
指针数组是存放指针的数组,显然数组指针就是指向数组的指针。
int (*p)[10];//[]的优先级高于*,所以加上括号,确保*和p先结合
不加括号int *p[10]就变成了指针数组。
数组指针的类型是 int (*)[10];
数组指针的初始化
int (*p)[10]=&a;//取首元素的地址进行初始化,二维数组则是第一行的第一个元素的地址
函数指针变量
字符,整型,数组都有地址,那么函数是否存在地址呢?通过地址调用函数。
由上图可知一个函数是存在地址的,而且它的性质和数组指针一样都可以用名来表示地址 。
那么如何来创建函数指针变量呢?
函数指针类型是int (*)(int x,int y)//这里只是以上述函数指针为例。
函数指针变量的使用
int mulp(int x,int y)
{
return x*y;
}
int main()
{
int (*pf)(int x,int y)=mulp;
int a=2,b=5,c=4;
printf("%d",pf(a,pf(b,c)));//非常方便的实现了函数的使用
}
函数指针数组
顾名思义函数指针数组就是存放函数指针的数组
那么函数指针数组怎么表示呢?
首先int (*p)()表示函数指针,int *a[10]表示指针数组
所以函数指针可以表示为int (*p[10])()
函数指针数组的应用————转移表
非常方便的实现了对多函数的调用
typedef关键字
typedef是用来类型重命名的,可以实现对复杂类型的简化
typedef int * ptr //对整型指针的简化,后面代码int *用ptr来表示
typedef int (*ptr)[10] //对数组指针的简化,后面代码改数组指针用ptr表示
typedef void(*ptr)() //同上
typedef的合理运用可以简化1代码,也可以增加代码的可读性