- 数组指针:指向数组的指针
int (*p)[n]
“()”的优先级高于“[]”,因此,p和“*”结合,构成一个指针,该指针名为p,int修饰的是数组的内容,即数组的每个元素。也就是说p是个指针,该指针指向具有n个整型的一维数组。
int (* arrPtr)[10] = NULL; // 一个指针,它指向一个有10个int元素的数组
int matrix[3][10]; // 数组名称是一个指向第一个元素的指针,也就是第一行的指针
arrPtr = matrix; // 使得arrPtr指向数组的第一行,在这种情况下,使用 arrPtr 获取元素的方式与使用 matrix 完全一样。例如,赋值运算(*arrPtr)[0]=5 等效于 arrPtr[0][0]=5 和 matrix[0][0]=5。
(*arrPtr)[0] = 5; // 将5赋值给第一行的第一个元素
++arrPtr; // 将指针移动到下一行
int arr[5]={1,2,3,4,5};
int (*p1)[5] = &arr; //&arr 是指整个数组的首地址,而 arr 是指数组首元素的首地址,虽然所表示的意义不同,但二者之间的值却是相同的
/*下面语句会有警告:从不兼容的指针类型初始化*/
int (*p2)[5] = arr; //左边的类型是指向整个数组的指针,而右边的数据类型是指向单个字符的指针
-
指针数组:具有指针类型元素的数组 (常常作为二维数组的一种便捷替代方式)
int *p[n]
“[]”的优先级高于“*”,因此,p先与“[]”结合,构成一个数组,数组名为p,(int * )修饰的是数组的内容,即数组的每个元素。也就是说p是个数组,该数组的元素是n个指向整型的指针。 -
函数指针:函数指针是一个指针,指向的是一个函数的地址。
函数指针是需要把一个函数的地址赋给它,比如:
int (*fun)(int x, int y);
fun = &Function; //或者 fun = Function;
x = (*fun)(); //或者 x = fun();
取址运算符&不是必须的,因为一个函数名就可以表示了它的地址,如果是函数调用,还必须包含一个圆括号包起来的参数表。
int add(int x, int y)
{
return x + y;
}
int sub(int x, int y)
{
return x - y;
}
//函数指针
int (*fun)(int x, int y);
int main(int argc, char *argv[])
{
fun = add; //第一种写法
int num1 = (*fun)(1,2);
printf("num1 = [%d]\n", num1);
fun = ⊂ //第二种写法
int num2 = fun(3,4);
printf("num2 = [%d]\n", num2);
return 0;
}
int (*f)(); //所指向的函数返回整型值
int *(*f)(); //所指向的函数的返回值是一个整型指针,必须对其进行间接访问才能得到一个整型值
int *f[]; //指针数组,元素类型是指向整型的指针
int (*f[])(); //f是一个数组,数组元素的类型是函数指针,它所指向的函数的返回值是一个整型值
int *(*f[])(); //这个声明创建了一个指针数组,指针所指向的类型是返回值为整型指针的函数
//把g声明为一个数组,数组的元素类型是一个函数指针,它所指向的函数接受两个参数,并返回一个整型指针
int *(*g[])(int , float);
//next是一个指针,它指向一个函数,该函数返回另一个指针,该指针指向一个类型为char的常量指针。
char * const *(*next)();
-
指针函数:指针函数是一个函数,是返回值为指针的函数。
注意:在调用指针函数时,需要一个同类型的指针来接收其函数的返回值。
普通的函数声明:int fun(int x , int y);
指针函数的声明:int* fun(int x, int y);
-
指针常量和常量指针
int *pi; //pi是一个普通的指向整型的指针。
int const *pci; //pci是一个指向整型常量的指针(指针常量)。可以修改指针的值,但不能修改它所指向的值。
int *const cpi; //cpi是一个指向整型的常量指针(常量指针)。指针是常量,它的值无法修改,但可以修改它所指向的整型的值。
int const *const cpci; //指针本身和它所指向的值都是常量,不能修改。
根据下标运算符的规则,表达式(*arrPtr)[i] 等同于 *((*arrPtr)+i)
- 函数指针数组
函数指针数组的作用是什么呢?它最大的作用就是可以简化代码,减少很多重复的不必要的代码。
例如下面这段代码
int main()
{
int x, y;
int input = 1;
int ret = 0;
do
{
printf("*************************\n");
printf(" 1:add 2:sub \n");
printf(" 3:mul 4:div \n");
printf("*************************\n");
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("输入操作数:");
scanf("%d %d", &x, &y);
ret = add(x, y);
printf("ret = %d\n", ret);
break;
case 2:
printf("输入操作数:");
scanf("%d %d", &x, &y);
ret = sub(x, y);
printf("ret = %d\n", ret);
break;
case 3:
printf("输入操作数:");
scanf("%d %d", &x, &y);
ret = mul(x, y);
printf("ret = %d\n", ret);
break;
case 4:
printf("输入操作数:");
scanf("%d %d", &x, &y);
ret = div(x, y);
printf("ret = %d\n", ret);
break;
case 0:
printf("退出程序\n");
breark;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
在switch中有很多完全重复的代码,如果我们用函数指针数组优化后是这样的。
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;
}