数组指针
一个指向数组的指针。落脚点在指针上面;指针的优先级必定比“[ ]”的优先级高
在这里我们插入一个问题:下面的声明合法吗?
int arr[10], *p = arr;
int brr[3][10], *q = brr;
第一个声明是合法的。它为一个整型数组分配内存,把p声明为一个指向整型的指针,并把它初始化为指向arr数组的第一个元素。arr和p具有相同的类型:指向整型的指针。但是,第二个是非法的,它正确的创建了brr数组,并把q声明为一个指向整型的指针。但是在这里,q的初始化是不正确的,因为brr并不是一个指向整型的指针,而是一个指向整型数组的指针。
那么,我们该如何声明?
int (*p)[10];
下标引用的优先级高于间接访问,但由于括号的存在,首先执行的还是间接访问,所以,p是一个指向整型数组的指针。对其加上初始化可得:
int (*p)[10] = brr;
它指向brr的第1行。
p是一个指向拥有10个整型元素的数组的指针,当把p与一个整数相加减的时候,该整数值首先根据10个整型值的长度进行调整,然后执行加法。所以可以使用这个指针一行一行地在brr中移动。
如果需要一个指针逐个访问整型元素而不是逐行在数组中移动,应该怎么办?
下面两个声明都创建了一个简单的整型指针,并以两种不同的方式进行初始化,指向brr的第一个整型元素:
int *pi = &brr[0][0];
int *pi = brr[0];
增加这个指针的值使它指向下一个整型元素。
指针数组
一个保存指针类型数据的数组。落脚点在数组上面
正如可以创建整型数组一样,也可以声明指针数组。下面举一个例子。
int *ar[10];
为了弄清这个声明,我们假设它是一个表达式,并对它进行求值。
下表引用的优先级高于间接访问,所以在这个表达式中,先执行下标引用,因此,ar是某种类型的数组,它包含的元素个数为10。再取得一个元素之后,随即执行的是间接访问操作,所以它的结果是一个整型值。
那么,ar到底是个什么东西呢?
对数组的某个元素执行间接访问操作后,我们得到一个整型值,所以,ar肯定是个数组,他的元素类型是指向整型的指针。
函数指针
这里我们引入一个简单程序:
#include<stdio.h>
int add(int a, int b)
{
return a+b;
}
int mul(int a, int b)
{
return a*b;
}
int main()
{
int a, b;
char op;//"+" "*"
scanf("%d%d", &a, &b);
scanf("%c",&op);
int (*pfun)(int, int);//定义一个函数指针,指向add 指向mul
//(*pfun)声明一个指针变量
if(op == '+')
{
pfun = add;
}
else
{
pfun = mul;
}
int res = pfun(a, b);
printf("%d", res);
}
结果却出现了一点意外:
2
3
6
输入2,回车;输入3,回车;还没有输入“+”或者“*”,结果直接就出来了,那么这是为什么呢?
原因在于输入缓冲区。我们将断点下到
scanf("%c",&op);
发现,此时的op等于“\n”。
在输完3的时候,回车之后,程序会把回车'\n'读到输入缓冲区中,以%c的形式获取。
对此,我们换一种形式来完成该函数指针的使用。
#include<stdio.h>
#include<string.h>
int add(int a, int b)
{
return a+b;
}
int mul(int a, int b)
{
return a*b;
}
int main()
{
int a, b;
char op[10] = {0};
scanf("%d%d", &a, &b);
scanf("%s",&op);
int (*pfun)(int, int);
if(strcmp(op,"+") == 0)
{
pfun = add;
}
else
{
pfun = mul;
}
int res = pfun(a, b);
printf("%d", res);
}
结果为:
2
3
+
5
%d %s 通常是以空格或者\n分割
%d %c 系统无法区分%d和%c之间的\n是换行还是字符,也就是把换行解析成了有效字符。如果我们先%c 再%d就可以避开该问题。