指针数组和数组指针
- 指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。
- 数组指针:首先它是一个指针,它指向一个数组。在 32 位系统下永远是占 4 个字节,至于它指向的数组占多少字节,不知道。它是“指向数组的指针”的简称。
那么下边俩个分别叫做什么呢?
int *p1[4];
int (*p2)[4];
第一个我们称之为指针数组。“[ ]”的优先级比“”要高。p1 先与“[ ]”结合,构成一个数组的定义,数组名为 p1,int 修饰的是数组的内容,即数组的每个元素。这是一个数组,其包含 4 个指向 int 类型数据的指针,即指针数组。
我们可以这样理解:
第二个我们称之为数组指针。在这里“()”的优先级比“ []”高,“*”号和 p2 构成一个指针的定义,指针变量名为 p2,int 修饰的是数组的内容,即数组的每个元素。数组在这里并没有名字,是个匿名数组。那现在我们清楚 p2 是一个指
针,它指向一个包含 4 个 int 类型数据的数组,即数组指针。
同样,也可以这样理解:
函数指针,函数指针数组和指向函数指针数组的指针
- 函数指针:就是函数的指针。它是一个指针,指向一个函数。
- 函数指针数组:它是一个数组,数组内存储了指向函数的指针。
函数指针数组指针:它是一个指针,只不过这个指针指向一个数组,这个数组里面存的都是指向函数的指针。
看如下例子:
char * (pf)(char p1,char * p2);
这个我们称之为函数指针。” * “号和 pf 构成一个指针的定义,指针变量名为 pf。pf指向一个函数,该函数的返回值类型是char * ,函数参数有两个,分别为p1和p2,p1和p2都是char * 类型.char * (pf[3])(char p);
这个我们称之为 函数指针数组。“[ ]”的优先级比“*”要高。pf 先与“[ ]”结合,构成一个数组的定义,数组名为 pf。数组内存储了 3 个指向函数的指针。这些指针指向一些函数,其中函数返回值类型为指向字符的指针,参数为一个指向字符的指针。char * ((*pf)[3])(char p);
这个称为 指向函数指针数组的指针。该 pf 确实是实实在在的指针。这个指针指向一个包含了 3 个元素的数组;这个数组里面存的是指向函数的指针;这些指针指向一些返回值类型为 指向字符的指针、参数为一个 指向字符的指针 的函数。
下面通过转移表了解一下函数指针数组的用法:
void menu()
{
printf("**************************\n");
printf("*******1.add 2.sub*****\n");
printf("********3.mul 4.div*****\n");
printf("****************0.exit*****\n");
printf("请选择:");
}
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 = 0;
int y = 0;
int input = 1;
int ret = 0;
int (*p[5])(int , int ) = { 0, Add, Sub, Mul, Div };//转移表
do
{
menu();
scanf("%d", &input);
if (input >=1 && input <=4)
{
printf("输入操作数:");
scanf("%d%d", &x, &y);
ret = p[input](x, y);
}
else
{
printf("输入错误,请重新输入:");
}
printf("ret=%d\n", ret);
} while (input);
system("pause");
return 0;
}
小试:
(* (void(*) ())0)();
void (* signal(int,void(*)(int)))(int);
第一个为函数调用。怎么理解呢?
首先 void (* )()是一个函数指针,该指针指向一个无参数,返回值类型为void型(即没有返回值)的函数。
(void (* )())0:就是将0强制转换成函数指针类型。
(* (void (*)())0):就是取0地址处开始的一段内存里面的内容,其内容就是保存在首地址为 0 的一段区域内的函数。
(* (void(*) ())0)():就是对函数进行调用。
第二个可以理解为:
signal是一个函数,其返回值类型为void (*) (int)型,即函数指针类型;参数有两个,分别为整形和函数指针类型。可简写为:
typedef void (*pfun_t) (int);
pfun_t signal(int , pfun_t);
回调函数:
就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数。
使用回调函数,模拟实现qsort。
int int_cmp(const void* p1, const void* p2)
{
if (*(int *)p1 > *(int *)p2)
{
return 1;
}
else if (*(int *)p1 < *(int *)p2)
{
return -1;
}
else
{
return 0;
}
}
void _swap(void *p1, void *p2, int size)
{
int i = 0;
for (i = 0; i < size; i++)
{
char tmp = *((char *)p1 + i);
*((char *)p1 + i) = *((char *)p2 + i);
*((char *)p2 + i)=tmp;
}
}
void mybubble(void *base, int count, int size, int(*cmp)(void *, void*))
{
int i = 0;
int j = 0;
for (i = 0; i < count - 1; i++)
{
for (j = 0; j < count - i - 1; j++)
{
if (cmp((char *)base + j*size, (char *)base + (j + 1)*size)>0)
{
_swap((char *)base + j*size, (char *)base + (j + 1)*size, size);
}
}
}
}
int main()
{
int a[] = { 1, 2, 2, 56, 32, 6, 8, 0 };
char *arr[] = { "aabb", "dddd", "bbbb", "eeee" };
int i = 0;
mybubble(a, sizeof(a) / sizeof(a[0]), sizeof(int), int_cmp);
for (; i < sizeof(a) / sizeof(a[0]); i++)
{
printf("%d ", a[i]);
}
printf("\n");
system("pause");
return 0;
}
指针概述: