指针数组 数组指针 函数指针 函数指针数组 指向函数指针数组的指针 的理解
首先我们要知道什么是指针
指针是C语言中广泛使用的一种数据类型。 指针是编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。简单来说,指针就是地址。
指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。
数组指针:首先它是一个指针,它指向一个数组。在32
位系统下永远是占4 个字节,至于它指向的数组占多少字节,不知道。它是“指向数组的指针”的简称
那我们来看下下面哪个是指针数组,哪个是数组指针
A int *arr1[10];
B int(*arr2)[10];
对于A来说 “[]”的优先级比“*”要高,arr1先与“[]”结合,构成一个数组的定义,数组名为arr1,int *修饰的是数组的内容,即数组的每个元素。那现在我们清楚,这是一个数组,其中包含10个指向int类型数据的指针,所以A就是一个指针数组。再对于B来说 在这里“()”的优先级比“[]”高,“*”号和arr2构成一个指针的定义,指针变量名为arr2,int修饰的是数组的内容,即数组的每个元素。 那我们就清楚 arr2是一个指针,它指向一个包含10个int类型数据的数组,所以B就是数组指针。
或许我们看了这些就更清楚了
指针数组 我们可以看出数组里面存放的全是指针(地址)。
数组指针 指向数组(和数组的首元素的地址相同)
函数指针
看名字我们就知道 函数指针就是函数的指针,他是一个指针指向一个函数。
void test()
{
printf(“hehe%d\n”);
}
我们看看下面fun1和fun2哪个有能力存放test函数的地址?
void(*pfun1)();
void*pfun2();
首先能存放地址肯定就是指针。 pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参数,返回值类型为void。
函数指针的使用:
1.
void Function()
{
printf("Call Function!\n");
}
int main()
{
void(*p)();
*(int*)&p = (int)Function;
(*p)();
return 0;
}
那我们会问“*(int*)&p = (int)Function;” 这表示什么意思呢
void(*p)();
这行代码定义了一个指针变量p,p指向一个函数,这个函数的参数和返回值都是void。
&p是求指针变量p本身的地址。
(int*)&p 表示将地址强制转换为指向int类型数据的指针。
(int)Function 表示将函数的入口地址强制转换为int类型的数据。
到这里我们就会明白,其实是表示将函数的入口地址赋值给指针变量p。
其实函数指针与普通指针没什么差别,只是指向的内容不同而已。
2.
(*(void(*)())0)() 看了这个表达式,简直要发狂了
第一步:void(*)(),这是一个函数指针类型。这个函数没有参数,没有返回值。
第二步:(void(*)())0,这是将0强制转换为函数指针类型,0是一个地址。即一个函数保存在首地址为0的一段区域内。
第三步:(*(void(*)())0),这是取0地址开始的一段内存里面的内容,内容就是保存在首地址为0的一段区域内的函数。
第四步:(*(void(*)())0)(),这是函数调用。
一步一步的分析,也就能看懂这个表达式。
函数指针数组
函数指针数组,顾名思义,就是一个指针数组,是数组。
我们来看个例子
char*(*pf[3])(char *p)
这是定义一个函数指针数组。他是一个数组,数组名为pf,数组内存储了3个指向函数的指针。这些指针指向一些返回值类型为指向字符的指针,参数为一个指向字符的指针的函数。
函数指针数组指针
函数指针的数组指针,它就是一个指针呀。只不过指针指向一个数组,这个数组里面存放的都是指向函数的指针。
char *(*(*(pf)[3])(char *p)
这里的pf与上面的pf就不是一个意思。上面的pf是数组名,而这里pf是指针。这个指针指向一个包含了3个元素的数组,这个数组里面存放的是指向函数的指针,这些指针指向一些返回值为指向字符的指针,参数为一个指向字符的指针函数。