本文最后更新于 621 天前,其中的信息可能已经有所发展或是发生改变。
高级指针专题
函数指针
int f(int);
int (*pf)(int) = &f;
第二个声明创建了函数指针 pf ,并把它初始化为指向函数 f
初始化表达式中的 & 操作符是可选的,因为函数名被使用时总是由编译器把它转换为函数指针
int ans;
ans = f(2);
ans = (*pf)(2);
ans = pf(2);
效果一致
回调函数
函数指针最常见的用途是把函数指针作为参数传递给函数以及用于转移表
//回调函数示例
#include <stdio.h>
#include "node.h"
//查找单链表中指定的值
//参数为void * 型,可以指向未知类型
Node *search_list(Node *node, void const *value,
int (*compare)(void const *,void const *))
{
while( node != NULL)
{
if( compare(&node->value, value) == 0)
break;
node = node->link;
}
return node;
}
//一个比较函数
int compare_ints(void const *a, void const *b)
{
//将void * 型强制类型转换
if(*(int *)a == *(int *)b)
return 0;
else
return 1;
}
转换表
创建转换表首先需要声明并初始化一个函数指针数组,需要确保这些函数的原型出现在这个数组声明之前。
double add(double, double);
double sub(double, double);
double mul(double, double);
double div(double, double);
//注意顺序
...
double (*oper_func[])(double, double) =
{
add,sub,mul,div,...
};
...
result = oper_func[oper](op1, op2);
命令行参数
C程序的 main 函数具有两个形参
int main(int argc, char **argv)
命令行示例
$ cc -c -o main.c insert.c -o test
-c -o main.c insert.c -o test
即为参数,这个数组的每一个元素都是一个字符指针,数组的末尾是一个 NULL 指针。argc 的值和这个 NULL 值都用于确定实际传递了多少个参数。argv 指向数组的第1个元素,所以它被声明为一个指向字符的指针的指针。
//处理命令行参数
#include <stdio.h>
#define TRUE 1
//执行实际任务的函数原型
void process_standard_input(void);
void process_file(char *file_name);
int option_a, option_b /* etc. */;
void main(int argc, char **argv)
{
//处理选项参数: 跳到下一个参数,并检查是否是横杠开头
while(*++argv != NULL && **argv == '-')
{
//检查横杠后面字母
switch(*++*argv)
{
case 'a':
option_a = TRUE;
break;
case 'b':
option_b = TRUE;
break;
/* etc */
}
}
//处理文件名参数
if(*argv == NULL)
{
process_standard_input();
}
else
{
do {
process_file(*argv);
}while(*++argv != NULL);
}
}
字符串常量
当一个字符串常量出现在表达式中,它的值是一个指针常量。
"xyz" + 1 表示第二个字符 y
*"xyz" 表示第一个字符 x
"xyz"[2] 表示第三个字符 z