高级声明:

int (*f)();

这里声明有两个括号,第二个括号是函数调用,第一个括号是聚组作用。(*f)是一个函数,所以f是指向返回整型的函数的指针。程序中的每个函数都位于,内存中某个位置,所以存在指向那个位置的指针。

int *f[];

下标的优先级高,所以f是个数组,数组中元素为指向int的指针。

int (*f[])()

首先按照优先级进行分析,括号内(*f[])先求值,所以*f[], f是数组,数组元素是指向某种类型的指针,结合外面的看,f是一个数组,数组元素是指向返回int类型的函数的指针。

函数指针:

指针在使用前需要进行初始化,对于函数指针,访问前需要初始化为指向摸个函数。

int fuc(int);

int (*fPtr)(int) = &fuc;
//在函数初始化之前需要具有fuc的原型,否则,编译器无法检查fuc的类型是否与fPtr一致。

初始表达式中的&操作符是可选的,因为函数名被使用时,总是由编译器把它转换为函数指针,&操作符只是显示的说明了编译器将隐式执行任务。

函数指针被声明后有三种方式调用函数:

int result;

result = func(25);
result = (*fPtr)(25);
result = fPtr(25);

第一种方法,直接调用,执行时函数名首先被转换成一个函数指针,该指针指向函数在内存中的位置。然后,函数调用操作符调用该函数,执行位于这个地址的代码

第二种方法,先间接访问,把函数指针转换成函数名,这个转换时不必要的,执行时还会像第一种方法一样被转换到函数指针。

第三种方法,间接访问时不必要的,编译器需要的是一个函数指针,这里直接使用函数指针。

函数指针也可以作为值,传入其他函数,叫做回调函数。例如下面的类型无关的链表查询函数。

#include <stdio.h>

typedef struct Node {
struct Node *next;
int value;
}Node; /*
* 这里值以及比较函数均是void类型,需要在使用时根据类型自己进行转换
* */
Node *search_list(Node *root, void const *value, int (*compare)(void const *, void const *))
{
Node *current = root;
while(current != NULL){
//回调函数进行比较
if(compare(&current -> value, value) == 0){
break;
}
current = current -> next;
} return current;
}
//声明为void *类型,和compare保持一致
int int_compare(void const *num1, void const * num2){
//根据类型进行转换
if(*(int *)num1 == *(int *)num2){
return 0;
}else {
return 1;
}
} int main()
{
Node third = {NULL, 3};
Node second = {&third, 2};
Node first = {&second, 1};
int target = 2; Node *result = search_list(&first, &target, int_compare); if(result == NULL){
printf("No Found\n");
}else{
printf("got it: %d", result -> value);
} return 0;
}

运行:

如果希望在value为字符的链表中查找,只需要将比较函数改为字符类型既可以。

指针数组的第二个应用就是转移表:

#include <stdio.h>

double add(double, double);
double sub(double, double);
double mul(double, double);
double div(double, double); //转移表中保存函数的指针,确保指针类型相同
double (*transTable[])(double, double) = {add, sub, mul, div}; int main()
{
printf("%g\n", transTable[0](1, 1));
printf("%g\n", transTable[1](2, 1));
printf("%g\n", transTable[2](3, 5));
printf("%g\n", transTable[3](4, 3)); return 0;
} double add(double a, double b)
{
return a + b;
} double sub(double a, double b)
{
return a - b;
} double mul(double a, double b)
{
return a * b;
} double div(double a, double b)
{
return a / b;
}

运行结果:

要注意转移表使用时,越界访问。

命令行参数:

命令行参数是指向指针的指针的另一个用武之地,参数传给C程序main时包含两个形参,argc和argv,argc是命令行参数的数目,argv是保存参数指针的数组。第一个是指向程序名称,末尾是一个NULL指针。

#include <stdio.h>

int main(int argc, char **argv)
{
int count = argc;
printf("count: %d\n", count); for(int idx = 0; idx < count; idx++)
{
printf("[%s]\n", argv[idx]);
} return 0;
}

编译选项添加两个参数

运行结果:

字符串常量:

字符串常量出现于表达式中,它的值是一个指针常量,编译器把这些指定字符拷贝一份储存在内存的某个位置,并储存一个指向第一个字符的指针。我们可以对他进行下标引用。

char *ch = "abcd"  + 1;

ch为指向b的指针。可以把字符串常量和数组名一样看待。

C和指针 第十三章 高级指针话题的更多相关文章

  1. C和指针 第十三章 习题

    1,1标准输入读入字符,统计各类字符所占百分比 #include <stdio.h> #include <ctype.h> //不可打印字符 int isunprint(int ...

  2. 《C和指针》 读书笔记 -- 第13章 高级指针话题

    1.函数指针 int (*f)(); int *(*f[])(); 用途: [1]回调函数 e.g. /*在一个单链表中查找指定值*/ Node *search_list(Node *node,voi ...

  3. 【WPF学习】第三十三章 高级命令

    前面两章介绍了命令的基本内容,可考虑一些更复杂的实现了.接下来介绍如何使用自己的命令,根据目标以不同方式处理相同的命令以及使用命令参数,还将讨论如何支持基本的撤销特性. 一.自定义命令 在5个命令类( ...

  4. 《C与指针》——高级指针话题

    指针真是让人又爱又恨..... 首先还是先来看一下C语言中的高级指针声明.不要被表面迷惑最重要. /* ** <C和指针>——高级指针话题 */ int i; //定义一个整型变量 int ...

  5. C++(指针和高级指针)-上篇

    [在指针中存储地址] int *pAge=nullptr; //将PAge声明为int指针,即用于存储int变量的地址 如果将指针初始化为0或者NUll,以后必须将变量的地址赋给它,如下例代码: ; ...

  6. C和指针 第六章 数组名与指针

    指针的算术运算符是指针和数组之间的一种关联,但不是唯一关联: 可以使用数组名作为指向数组第一个元素的指针,但是不可以给数组名赋新的值. //如下声明a int a[10]; //用a作为指向数组第一个 ...

  7. 联合与枚举 、 高级指针 、 C语言标准库(一)

    1 输入一个整数,求春夏秋冬 1.1 问题 在实际应用中,有的变量只有几种可能取值.如人的性别只有两种可能取值,星期只有七种可能取值.在 C 语言中对这样取值比较特殊的变量可以定义为枚举类型.所谓枚举 ...

  8. JavaScript高级程序设计:第十三章

    第十三章 一.理解事件流 事件流描述的是从页面中接收事件的顺序. 1.事件冒泡 IE的事件流叫做事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点.以下面的HTML页面为例: ...

  9. C和C指针小记(十三)-数组

    1.1 一维数组 一维数组的声明: int a[10]; 这里a就是一个数组. 数组a的类型就是一个指向整型的常量指针. 但是数组和指针是**不相同**的. **数组具有特定数量的元素,而指针只是一个 ...

随机推荐

  1. Winform布局方式

    一.默认布局 ★可以加panel,也可以不加: ★通过鼠标拖动控件的方式,根据自己的想法布局.拖动控件的过程中,会有对齐的线,方便操作: ★也可选中要布局的控件,在工具栏中有对齐工具可供选择,也有调整 ...

  2. 查找数据库中重复的值的数据,having的使用,count(1),sum等聚会函数

    通过having代替where来使用count(1),sum()等函数.譬如如下数据id value1 21 32 33 53 6 可以写个语句统计value的分组 在这里,可以省略前面的sum(va ...

  3. java多线程系类:JUC原子类:04之AtomicReference原子类

    概要 本章对AtomicReference引用类型的原子类进行介绍.内容包括:AtomicReference介绍和函数列表AtomicReference源码分析(基于JDK1.7.0_40)Atomi ...

  4. cf Round 603

    A.Alternative Thinking(思维) 给出一个01串,你可以取反其中一个连续子串,问取反后的01子串的最长非连续010101串的长度是多少. 我们随便翻一个连续子串,显然翻完之后,对于 ...

  5. 利用DotSpatial发布WMS, WFS服务

    我们遇到的几个给政府部门做的GIS系统,一般都只要面子,只要好看,领导高兴得不得了,点点这里点点那里,哟,这按钮一点还会转,领导开心得跟朵花似的...要是搞个各种分析什么的全堆上来,他就嫌烦了...这 ...

  6. arduino红外遥控库IRremote的IRsend类sendRaw函数溢出问题及其解决方法

    最近在调试红外遥控格力空调,在论坛中学到了不少东西.参考: (1)<解决问题系列(4)——红外编码分析利器使用> (2)<315Mhz模块传输替代315Mhz遥控器> 调试环境 ...

  7. hdu2586 LCA

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  8. ssh中org.springframework.orm.hibernate4.support.OpenSessionInViewFilter的作用及配置

     org.springframework.orm.hibernate4.support.OpenSessionInViewFilter 是Spring为我们解决Hibernate的Session的关闭 ...

  9. awk中的system和getline的用法

    system只能对命令的输出结果输出到终端. getline在awk中可以使命令的输出结果传到一个变量中保存. # awk 'BEGIN{system("date")|getlin ...

  10. 文本框 textarea 动态显示行数(简单文本编辑器)

    工作需求做一个文本编辑器简单的. 右边输入文字,左边会显示相应的代码行.清空也会变为1. 废话不多说上代码,自己理解. <style type="text/css"> ...