函数指针

1、

我们先看一个简单的加法:

#include<iostream>
int Add(int a,int b)
{int c = a + b;return c;
}
int main()
{int x = 2, y = 3;int z = Add(x,y);printf("Sum = %d\n", z);
}

运行结果:

我们使用指针来改变上的代码:

#include<iostream>
int Add(int *a,int *b)
{int c = *a + *b;return c;
}
int main()
{int x = 2, y = 3;int z = Add(&x, &y);printf("Sum = %d\n", z);
}

运行结果:

把返回值,转换成返回地址:

#include<iostream>
int *Add(int* a, int* b)
{int c = (*a) + (*b);return &c;
}
int main()
{int a = 2, b = 3;int* ptr = Add(&a, &b);printf("Sum = %d\n", *ptr);
}

运行结果:

注意:

(1)

int *Add(int* a, int* b)
{int c = (*a) + (*b);return &c;
}

这里的函数Add()前面加了个 *,代表返回指向整数的指针。

上面的代码运行正确,其实有个逻辑错误。

我们来继续看一个例子,我们在 mian()函数 增加一个打印 " hello world "的函数。

#include<iostream>void helloworld()
{printf("hell world!");
}
int *Add(int* a, int* b)
{int c = (*a) + (*b);return &c;
}int main()
{int a = 2, b = 3;int* ptr = Add(&a, &b);helloworld();printf("Sum = %d\n", *ptr);
}

运行结果:

注意:

" hello world!" 可以打印,但 值 现在不能打印了。为什么? 这是因为内存栈的一个问题。怎么说?

用程序的运行来看内存变化:

首先我们的代码是 在内存栈中建立了main()函数,下面就会有变量a,b,还有*ptr,好了,然后开始调用函数Add()函数,内存的栈的位置又划出新的内存来提供给Add()函数,它有指针变量 *a,*b,还有c,而*a ,*b指向main()函数的a和b的值,然后相加得c,输出c的地址。okay,这时程序又回来main()函数,之前的Add()函数已内存释放,我们开始执行helloworld()函数,内存栈又要给hellworld()函数提供内存,这时内存栈提供的内存的位置是之前Add()函数的内存位置,也就是说ptr目前还是指向c的值,但是helloworld()把Add()之前的内存位置给覆盖了,而这时Add()返回的c的地址已经被清空了。所以导致输出提示错误。

我们需要使用 malloc 来解决这个问题:

#include<iostream>void helloworld()
{printf("hell world!\n");
}
int *Add(int* a, int* b)
{int* c = (int*)malloc(sizeof(int));*c = (*a) + (*b);return c;
}int main()
{int a = 2, b = 3;int* ptr = Add(&a, &b);helloworld();printf("Sum = %d\n", *ptr);
}

运行结果:

2、

把函数作为地址:

#include<iostream>int Add(int a,int b)
{return a+b;
}int main()
{int c;int (*p)(int,int);p = &Add;c = (*p)(2,3);printf("a + b = %d\n", c);
}

运行结果:

非常酷,我们只是使用了一个函数指针来引用一个函数。

注意:

(0)

int (*p)(int,int);

因为我要指向Add(int a, int b)函数,这个函数有两个整型类型,我们这里我们必须和它一致,否则运行出错。

另外  Add(int a, int b) 返回的是一个整型int,所以这里也需要这条语句最前面也需要一个int,否则运行出错。

(1)

int (*p)(int,int);

(*p) 如果去掉括号,就变成了一个指向整型的指针。加上括号那就是函数指针

(2)

p = &Add;

这句语句,去掉 & 符号,也是可以运行的。

(3)

c = (*p)(2,3);

上面的语句可以用这种含有标识符的来引用,下面这句语句也是可以函数变量来引用:

c = p(2,3);

实现一下:

#include<iostream>int Add(int a,int b)
{return a+b;
}int main()
{int c;int (*p)(int,int);p = Add;c = p(2,3);printf("a + b = %d\n", c);
}

运行结果:


算法和数据结构是程序的第一秘诀,缺之算法和数据结构是编程的最大原因。

C ++ 指针 | 指针与函数_7相关推荐

  1. C++ 笔记(14)— 指针(指针声明、取地址、取值、new/delete、NULL指针、指针运算、指针数组、数组指针、指针传递给函数、从函数返回指针)

    1. 声明指针 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址.就像其他变量或常量一样,您必须在使用指 针存储其他变量地址之前,对其进行声明. 指针变量声明的一般形式为: type * ...

  2. C指针6:指针变量作为函数参数

    在C语言中,函数的参数不仅可以是整数.小数.字符等具体的数据,还可以是指向它们的指针.用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着 ...

  3. C++成员变量指针和成员函数指针【The semantics of funcitons】

    原文:https://blog.csdn.net/laojiu_/article/details/68946915 (原文有笔误) 1. #include <cstdio> #includ ...

  4. 用指针、子函数的方法去一维数组中所有元素的平均值,并放在a[0]处

    <程序设计基础实训指导教程-c语言> ISBN 978-7-03-032846-5 p142 7.1.2 上级实训内容 [实训内容7]用指针.子函数的方法去一维数组中所有元素的平均值,并放 ...

  5. 多态指针访问虚函数不能被继承的类快速排序N皇后问题插入排序堆排序merge归并排序栈上生成对象两个栈实现一个队列...

    多态 /*1. 要想实现覆盖(重写)父类必须声明为virtual,子类可以不声明为virtual.-->FunB()2. 派生类重写基类的虚函数实现多态,要求函数名.参数列表.返回值完全相同.( ...

  6. 对C语言 结构指针变量做函数的参数 结构作为函数的参数

    一.结构指针变量做函数的参数 /* 用指针变量作函数参数进行传送,这时由实参传向形参的只是地址,从而减少了时间和空间的开销. */ /* 计算一组学生的平均成绩和不及格的人数,用结构指针变量作函数参数 ...

  7. 【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  8. c语言键盘回调函数键盘的码,深入浅出剖析C语言函数指针与回调函数(三)

    前面两篇文章: http://blog.csdn.net/morixinguan/article/details/65494239 http://blog.csdn.net/morixinguan/a ...

  9. C++函数指针与回调函数

    [转自]cnblogs.com/chenyuming507950417/archive/2012/01/02/2310114.html 今天讨论下C/C++中的回调函数. 在理解"回调函数& ...

  10. 指针||指针和数组||指针和函数||指针、数组、函数 案例描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序

    指针 指针的基本概念 指针的作用: 可以通过指针间接访问内存 内存编号是从0开始记录的,一般用十六进制数字表示 可以利用指针变量保存地址 指针变量的定义和使用 指针变量定义语法: 数据类型 * 变量名 ...

最新文章

  1. 巧用二进制,让性能提升100倍,让存储空间减少100倍
  2. 实力封装:Unity打包AssetBundle(大结局)
  3. Mac 安装md5sum等
  4. redhat下给普通用户增加sudo命令,让他可以获得修改等权限
  5. 浅谈Log4net在项目中如何记录日志
  6. CCNA-第一篇-基础入门概念
  7. 当前,我们的DJANGO项目的requirements.txt文件
  8. 【杂谈】excel列表创建后,怎么删除蓝色边框线?
  9. 浙江大学-英特尔嵌入式技术中心成立
  10. yolov5数据集txt解析
  11. grub4dos挂载iso linux,GRUB4DOS加载ISO启动光盘完美解决方案
  12. Win10如何将语言栏移回右下角
  13. Class 类文件结构解析
  14. 计算机实验小学教导主任,小学教导主任2020年度考核个人总结5篇
  15. layui中实现动态的cols表头字段
  16. 基于SVD算法的电影推荐系统实验
  17. SSH端口转发Forwarding及隧道Tunneling
  18. solidworks动画制作教程——装配体爆炸动画
  19. Adobe也封杀中国账号了,技术管理者如何做到有备无患
  20. Array.of()

热门文章

  1. python原类、类的创建过程与方法
  2. linux系统时间和硬件时间的修改,Linux修改日期、时间,系统与硬件时间
  3. Windows 10下高效工作——快捷键一览
  4. 【李宏毅机器学习】Brief Introduction of Deep Learning 深度学习简介(p12) 学习笔记
  5. LeetCode-226. 翻转二叉树
  6. Centos7配置本地yum安装源出现错误
  7. libevent c++高并发网络编程_【多线程高并发编程】Callable源码分析
  8. 360 c语言 笔试,奇虎360校招的笔试真题
  9. linux mysql df_Linux基础:df命令总结
  10. ubuntu jdk tomcat mysql_Ubuntu下JDK+Tomcat+MySql环境的搭建