Appearance
高级指针
并不是所有的都是有用的,部分是为了找乐子
指向指针的指针
C
int i;
int *pi;
int **ppi;
ppi = π
*ppi = &i;//把三个变量联系起来
int ***pppi = &ppi;
间接访问的层数越多,使用的越少
高级声明
C
int *f();//返回指针的函数
int (*f)();//函数指针
int *(*f)();//指向返回指针的函数的指针
加入数组
C
int f[];
int *f[];
int (*f)();//函数指针
int f()[];//f是一个函数,返回一个数组,是违法的,函数只能返回标量
int f[]();//f是一个数组,成员是返回值为整形的函数,也是非法的,函数的长度不同
int (*f[])();//(*f[])==>f是参数为某种指针的函数,函数指针的数组,函数返回值为整形
int *(*f[])();//返回值为整形指针
int (*f)(int, float);
int *(*g[])(int, float);
函数指针
C
int f(int);
int (*pf)(int) = &f;//&是可选的
在函数指针赋值之前,必须要有函数的原型,用来检查类型是不是一致
函数名在使用之前总是被转化为函数指针,使用&只是声明了编译器隐式执行的任务
C
//使用
int ans;
ans = f(25);
ans = (*pf)(25);
ans = pf(25);
回调函数
C
//在一个单列表之中寻找一个值
Node *search_list(Node *node, int const value)
{
while(node != NULL)
{
if(node->value == value)
break;
node = node->link;
}
return node;
}
这个函数只能解决整形的列表传值
C
#include <stdio.h>
#include "node.h"
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;
}
这里使用的是相等的时候返回0,为了和系统函数相互兼容,负值表示第一个参数小于第二个参数,正值表示第一个参数大于第二个参数
C
int compare_ints(void const *a, void const *b)//声明为void*是为了匹配函数的原型
{
if(*(int *)a == *(void *)b)
return 0;
else
return 1;
}
比较字符串可以直接使用strcmp函数,但是有可能会报告函数的参数类型不匹配,它的参数是char *
转移表
把具体的操作封装成函数,与操作的选择分割开来
转移表是一个函数指针的列表,但是在创建列表之前要有每个函数的原型
C
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...
}
//使用
rseult = oper_func[oper](op1, op2);
**注:**数组的越界有可能会引起跳转进入其他函数,引起很难考察的错误
命令行参数
用户在命令行之中编写参数
传递命令行参数
main函数有两个参数,第一个argc,表示命令行参数的树木,第二个argv指向一组参数
C
int main(int argv, char **argv)
第一个参数是程序的名字,当一个函数有不同的调用方式的时候就有用了
C
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main(int argc, char **argv)
5 {
6 while(*++argv != NULL)//跳过第一个程序名
7 printf("%s \n", *argv);
8 return EXIT_SUCCESS;
9 }
处理文件传入的参数
C
1 #include <stdio.h>
2 #define TRUE 1
3 void process_standard_input(void)
4 {//处理用的函数
5 printf("over");
6 }
7 void process_file(char *file_name){
8 printf("open : %s\n", file_name);
9 }
10
11 int option_a, option_b;
12
13 void main(int argc, int **argv){
14 while(*++argv != NULL && **argv == '-'){ //处理参数, 访问第一个字符,从左到右进行,先判断非空
15 switch(*++*argv){ //运算方向从右向左,同一级符号
16 case 'a':
17 option_a = TRUE;
18 printf("a");
19 break;
20 case 'b':
21 option_b = TRUE;
22 printf("b");
23 break;
24 }
25 }
26 if(*argv == NULL)//处理文件
27 process_standard_input();
28 else{
29 do{
30 printf("laile");
31 process_file(*argv);
32 }while(*++argv != NULL);
33 }
34 }
每个‘ - ’可以有多个参数
C
while((opt = *++*argv) != '\0'){
switch(*++*argv){ //运算方向从右向左,同一级符号
case 'a':
option_a = TRUE;
printf("a");
break;
case 'b':
option_b = TRUE;
printf("b");
break;
}
字符串常量
当一个字符串常量出现在表达式中,他的值是一个指针常量,和数组名类似
C
"xyz" + 1
*"xyz"
"xyz"[2]
*("xyz" + 4) //出错
把十进制的数字转化为十六进制
C
#include <stdio.h>
void binary_to_ascii(unsigned int value)
{
unsigned int quotient;
quotient = value / 16;
if(quotient != 0)
binary_to_ascii(quotient);
putchar("0123456789abcdef"[value %16]);//进行对应的转换
}
C
void print_star(int n)
{//根据传入的数字打印你对应数量的星星
n += 5;
n /= 10;
printf("%s\n", "**********"+10 -n);
}
示例
C
int **(*abc[6])();
返回值为int指针的指针的函数的指针组成的数组
C
int **abc[6];
int型指针的指针组成的数列
C
int *(*abc)[6]
指向int的指针组成的数组的指针
C
int *(*abc())()
返回值为int指针的函数的指针作为abc函数的返回值
C
int (**(*abc)())()
返回值为int型的的函数的指针的指针的函数指针
C
int (*(*abc)())[6]
返回值为指向int型数组指针的函数指针
C
int *(*(*(*abc)())[6])()
返回值为int型指针的函数指针的数组的指针的函数指针
int *(*(*函数主体)[6])()
在外面的都是函数的返回值
第一个* 是最外层的返回值 int *()()
第二个*是和最后面的括号组成函数指针int *(*[6])()
第三个*是对于数组求指针
总结
确定函数的主体
函数的返回值的确定
从内向外单独的* 是对外面的结果求指针
数组是对外层的结果进行求数组
int *(*[6])()