Skip to content

高级指针

并不是所有的都是有用的,部分是为了找乐子

指向指针的指针

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])()