关于int *p[n]、int(p)[n]、intp()和int(*p)()详细实例解释
指针是C/C++语言中最精彩部分,话不多说,下边对这四种形式进行寻根问底,进行剖析。
- int *p[n];
- int(*p)[n];
- int*p();
- int(*p)();
看似好像乱的不像话,但是它理解起来并没有那么难懂,注意注意,下边是正文部分。
提示:要区分这四个的区别,可以从运算符优先级的层面来看差异,C语言中,[]和()的优先级比 * 的优先级高。
一、int *p[n]
根据优先级,int *p[n]等价于int *(p[n]),那p[n]顾名思义就只是一个数组而已,前边加一个 * ,就变成了数组指针了,即这个一维数组里边n个变量都是指针变量。
这样一来的便捷之处在于可以一次定义很多指针,如果需要很多同类型的指针的话,这么做很省事,事实上确实如此:
测试代码001
#include<stdio.h>
int main()
{
int* p[3]; //定义一个指针数组
int* q1, * q2, * q3; //定义三个指针变量
int a = 10, b = 20, c = 30; //定义整型变量,便于后边检验
p[0] = &a;
p[1] = &b;
p[2] = &c;
q1 = &a;
q2 = &b;
q3 = &c;
printf("%d\t%d\t%d\n", *p[0], *p[1], *p[2]);
printf("%d\t%d\t%d\n", *q1, *q2, *q3);
return 0;
}
这里是输出结果:
可以看出:
- int *p[n]是定义了一个指针数组,数组中的每一个元素都是一个指针变量
- 每一个数组指针变量都和普通变量没有区别
- 要注意使用数组指针变量时,下标的范围,不要越界
二、int(*p)[n]
到这里,*p不能简单地只看做是 *p=a(假定a是一个整型变量),应该比较着来看:
int a[3][4];
int (*p)[4];
第二个式子表示定义了一个指针变量p,p所指的对象是包含4个int型元素的一维数组,可能有点绕,我们来看一下代码:
测试代码002
#include<stdio.h>
int main()
{
int a[3][4]={ 1,2,3,4,5,6,7,8,9,10,11,12 };
int(*p)[4];
p = a; //p是一个二维指针,此时指向a[0]
p[0][0] = a[0][0]; //p相当于a,但p是一个变量
*(*(p + 1) + 1) = a[1][1];
printf("%d %d\n", p[0][0], *(*(p + 1) + 1));
return 0;
}
运行结果是这样的:
是不是有点明白定义的这个p是什么东西了?是的,你的直觉正确。
- int(*p)[4]定义出来的指针p,相当于二维数组a[3][4]的a
- p指向二维数组a的行a[0]
如果还是不太清楚,我们继续看一段实例代码:
测试代码003
#include<stdio.h>
int main()
{
int a[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
int(*p)[4]; //定义p为指针变量,指向含有4个int型元素的一维数组
int i, j;
p = a; //p指向二维数组a的行a[0]
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
printf("%d ", *(*(p + i) + j));
printf("\n");
return 0;
}
这下子是不是就释然了?
别急,我们继续强化一下(方便认识起见,自行把a脑补成p):
表示形式 | 含义 | 地址 |
---|---|---|
a | 二维数组名 | 1000 |
a[],*(a+0),*a | 第0行的首地址,即[0][0]的首地址 | 1000 |
a+2,&a[2] | 第二行的首地址 | 1016 |
a[2],*(a+1) | 第二行的首地址,a[2][0]的地址 | 1016 |
a[2]+2,* (a+2)+2,&a[2][2] | 第二行第二列的元素a[2][2]的地址 | 1024 |
* (a[2]+2),* (*(a+2)+2),a[2][2] | 第二行第二列的元素a[2][2]值 | 1024 |
三、int*p()
当出现(),那这种形式就是一种函数,那现在的问题是int*p()函数和int(*p)()有什么区别,如果有一个fun函数,其定义为:int fun(int a,int b);
那我们很好理解,这就是一个普通的函数,返回值为int型,但是如果我们把它转换成int *fun(int a,int b),同理,这也是一个函数,只不过返回值为指针类型(加 * 的fun函数为指针函数,其返回的指针指向一个整型变量)
老样子,看个代码就明白了。
测试代码003
#include<stdio.h>
int main()
{
int a = 4, b = 5;
int *pluse; //指针Pluse用来接收指针函数返回的值
int* sun(int* p, int* q); //声明一个指针函数
pluse = sun(&a, &b);
printf("%d\n", *pluse);
}
int* sun(int* p, int* q)
{
int s;
s = *p + *q;
return &s; //返回s的地址
}
运行结果当然也就很明了了,屏幕上蹦出一个9,就结束了,当然,对于这个int*p()讲到这里,最重要的是要记得,这个是
因为函数返回的类型是指针,所以就叫指针函数咯,这样记还是比较简单的。
四、int(*p)()
对于函数的概念这里就不在多说了,值得一提的是,每个函数都要占用一段连续的存储空间,而函数名就是这段内存区域的首地址,讲到这里,我们其实就可以想,如果把这个首地址赋给一个指针变量,那就可以调用指针来实现函数的功能了,没错,事实就是这样,而这样的函数叫做函数指针(把函数当成一个指针来看),其形式就是int(*p)(),
赶紧上车,看代码去:
#include<stdio.h>
int max(int a, int b) //取a,b的最大值
{
if (a > b) return a;
else return b;
}
int main()
{
int a = 1, b = 2;
int z;
int (*p)(int, int); //定义一个函数指针
p = max; //这个函数指针指向定义的函数
z = (*p)(a, b);
printf("%d\n", z);
return 0;
}
函数指针是比较容易理解的,但在这里要提两点注意的:
- 函数指针变量不能进行算术运算,这是与数组指针变量不同的,数组指针变量加减一个整数可以使指针移动,但是这里你要是想让函数指针变量移动的话,估计,,,只能说你很有想法
- 函数调用时“(*指针变量名)”两边的括号一定一定不能少,其中的“ * ”不要理解为指针运算,此时的它只是一种指示符号
- 我强调一下,这个是:
我们再来小小比较一下这两个函数:
形式 | 名称 |
---|---|
int*p(); | 指针函数 |
int(*p)() | 函数指针 |
总结
以上就是本次对C/C++中关于int *p[n]、int(p)[n]、intp()和int(*p)()详细介绍,当然,以上的代码都是用C语言敲写,如果看着难受,也可以用C++咯,那就这样,下次见。