函数指针
当声明一个函数指针时,必须声明它指向的函数类型,即要指出函数的返回类型以及函数的参数类型。
声明一个指向特定函数类型的指针的简单方法是,首先声明一个该类型的函数,然后用( *pf )形式的表达式代替函数名称
int f1 (int); //声明一个返回类型为void 、具有一个int型参数的函数f1
int ( *pf) ( int ); //用(*pf)代替f1
上面声明创建了函数指针pf,(int)表示函数,且参数为int 型,(*pf )表示pf是一个指向函数的指针,返回类型为int。f1 与(*pf)是相同类型的函
数,可以对 pf 进行赋值。
int an;
pf = f1; //f1是函数f1(int)的地址
an = f1( 12 );
an = (*pf) ( 12 );
an = pf( 12 );
上面三条对an赋值的语句等价,第二条语句把函数指针转换为一个函数名。
函数指针典型的用法是,作为参数传递给另一个函数。例如在对一个数组进行排序涉及到比较两个元素以决定哪个元素放在前面,如果是整形数,可以用>运算符;如果是字符串或者结构,需要一个函数用来比较。例如以下函数原型:
void show ( int ( *fp ) ( int ), char *str )
声明了show()函数有两个参数 fp 和 str,fp是一个函数指针,指向一个接受一个 int 型参数且返回类型为 int 型的函数,show()和 f1()函数可以做如下实现
void show( int ( * fp ) (int ), char * str)
{
int len=strlen(str) , s; //字符 str 长度
s=fp( len ); //将fp作用与len,得到返回值
printf("strlen(str)>10?%d\n",s); //判断 str 长度是否大于10
}
int f1( int n)
{
if(n>10)
return 1;
else
return 0;
}
因此可以如下调用show()函数
char str[10] = "123456";
show( f1, str);
回调函数
在单链表中查找一个值,它的参数指向链表头结点的指针以及指向需要查找的值的指针(不管这个值的类型)
struct node
{
int data; //声明不同类型时,comp函数不同
struct node *next;
}
struct node * find_list( struct node * pn, void const * value, int ( * comp)( void const *, void const * ) )
{
while( pn != NULL )
{
if( comp( &pn->data, value ) == 0 ) //comp比较 *value 和 &pn->data 两个地址处的数据,并返回结果值
break;
pn = pn->next;
}
return pn;
}
参数类型声明为void *, 表示一个指向未知类型的指针
在一个特定的链表中进行查找时,编写一个适当的比较函数comp (),并将它指向该函数的指针和指向需要查找的值的指针传递给查找函数。在使用比较函数的指针之前,它们必须被强制转换为正确的类型。
/* 对整型链表的查找 */
int comp(const void *p1, const void *p2)
{
return *(int *)p1 - *(int *)p2;
}
/* 对字符串链表的查找 */
struct node
{
char data[10];
struct node *next;
}
int comp( void const *p1, void const *p2 )
{
return strcmp((char*)p2, (char*)p1);
}
字符串常量
当一个字符串常量出现在表达式中时,它的值是个指针常量。当数组名和指向字符串常量的指针用于表达式时,可以对它们进行下标引用、间接访问以及指针运算,这些对于字符串常量是表示也有意义呢?下面这个表达式是什么意思?
"xyz" + 1
由于 "xyz" 实际上是一个指针,因此这个表达式的意思是:指针值加1的值,结果还是一个指针,指针字符串中的第2而字符 y,因此对于下面的表达式就可以很好理解了
*"xyz"
"xyz" [2]
对一个字符串常量进行间接访问的结果是指针所指向的字符 x,并不是整个字符串,而只是第一个字符字符串常量表达式可以用于数值转换为字符
putchar( "0123456789ABCDEF" [value % 16 ] );
余数将是一个 0~15 的值,使用下标从字符串常量中选择一个字符进行打印,该字符与余数大小对应。