1、首先,注意一点,千万不要解引用未被初始化的指针。
比如,参考下面的例子:
int *pt; //未被初始化,也就是没有给这个指针一个地址,而是只分配了存储这个指针本身的地址,而没有分配存储数据的内存
*pt = 5;
由于这样并没有初始化该指针,系统只分配了空间去存储这个指针,而没有分配空间去存储指针指向的地址将要存储的数据,所以,如果这时候解引用,5将不知道要被存储在哪里!
2、一些比较复杂的声明
- int board[8][8]; //声明一个内含int数组的数组
- int **ptr; //声明一个指向指针的指针,被指向的指针指向int
- int *risks[10]; //声明一个内含着10个元素的数组,每个元素都是一个指向int的指针
- int (*risks)[10]; //声明一个指向数组的指针,该数组内含10个数组元素
- void (*pf)(char *); //pf是一个指向函数的指针
- void *pf(char *); //pf是一个返回字符指针的函数
这里要注意的几点是:
- []和()运算符优先级是一样的,但是都比*要更高
- []和()都是从左往右的结合顺序
有了上面这两点,就可以很轻松的判断出一个复合结构是什么的类型,其含义是什么
3、函数与指针的用法
首先,可以将函数指针作为参数传入一个函数,比如下面这个例子:
void show(void (* pf)(char *),char *str);
这里声明了两个参数,其中参数1是pf,pf形参是一个函数指针,str是一个数据指针,也就是说,第一个传入的参数必须是一个函数的指针,而且,对于这个作为形参传入的函数,也是有要求的,返回类型必须是void,参数是一个,类型为char *,只要是这样形式的函数,其地址指针都可以作为形参传入该函数。
如果要使用typedef的话,还可以这样声明:
typedef void (*V_FP_CHARP)(char *);
在如上这样声明后,就可以如下声明一个函数指针了,被声明的函数返回值类型为void,参数为char *类型,且只有一个参数。
V_FP_CHARP pfun;//声明的指针指向一个形参为char *类型,返回值类型为void类型的函数。
如下再举例几种用法:
注意啦!!!:
在声明并定义如下函数后:
void ToUpper(char * str)
{
......
......
}
-----------------分隔符-------------------
void ToLower(char * str)
{
......
......
}
-----------------分隔符-------------------
void Transpose(char * str)
{
......
......
}
-----------------分隔符-------------------
void Dummy(char * str)
{
......
......
}
-----------------分隔符-------------------
void show(void (*pf)(char *),int n)
{
......
......
}
因为函数show(void (*pf)(char *),int n)的第一个参数可以传入一个函数指针,并且呢,前面定义的四个函数的类型完全符合参数规范,因此这四个函数的函数名可以作为函数指针传入该函数的第一个参数。因为前面定义过了V_FP_CHARP ,所以下面拿来直接使用,如下面这样处理过后,就可以很方便的通过数组的方式传入参数实现不同的功能啦!
V_FP_CHARP arpf[4]={ToUpper,ToLower,Transpose,Dummy};
如果你要使用show()函数来实现一定的功能的话呢,就可以如下
int index; //作为一个变量,控制要传入哪个函数,实现不同的功能
show(arpy[index],copy); //随着index值的改变,show()函数实现的功能也是不一样的
但是,当show()函数要求参数是一样的,但是又要实现不同的功能怎么办呢,就比如传入两个整形数,要求对其进行加减乘除四种不同的运算,这时候我们可以如下操作:
int (*p[4])(int,int); //首先,int *p[4]声明了含着四个元素的数组,每个元素都是一个指向int的指针
p[0] = fun1;
p[1] = fun2;
p[2] = fun3;
p[3] = fun4;
p[index] (10,20);
改变传入的index的值,就可以使函数实现不同的功能啦!