C++中的指针,指针函数和函数指针
指针是C或C++中的一大难题,因此弄懂指针对C和C++的学习有很大的帮助,最近一直在研究指针,因此写一篇随笔把心得记录一下。
简单来说指针也是一种变量,只不过指针变量所存储的不是我们直观上看到的,而是内存中的地址。如:

我声明了一个整型变量a并初始化为5,声明一个整型指针变量b,并且把a的地址赋给它,因此如果我们直接输出b的话就会得到a的地址,而输出*b就会得到a的值。
注意我的声明语句, int *b; int说明这是整数类型的变量,而*表明这是一个指针变量,合起来就是b是一个整型指针变量,变量名是b而不是*b.这一点很重要。
因此指针变量的声明方法为:
type *variableName;
type是数据类型,variableName是变量名。
这是很简单的一个指针变量的例子,复杂一点的话,我们看看另一种类型的指针:指向指针的指针。如:
#include <iostream>
using namespace std;
int main() {
int num = ;
int *a = #
int **b = &a;
cout << b << " = " << &a << endl;
cout << *b << " = " << a << endl;
cout << **b << " = " << *a << endl;
return ;
}
上例中我先生命了一个int并初始化为5,然后声明一个指针变量a并把num的地址赋值给它,然后再声明一个指针变量b并把a的地址赋值给它,分析一下上述程序会输出什么呢?
首先第一行输出,b=a的地址,因为我们赋值的时候就是这么赋值的,这很好理解。
第二行输出num的地址=num的地址,为什么呢?我们看看,a的值是什么?没错,是num的地址,那么*b是什么?当然就是a的地址存储的东西,那是什么呢?不就等于a吗?
第三行输出5=5,首先*b = &num, 那么*(*b)不就是&num中存储的东西吗?那不正是num,所以输出5=5。
还有一个要点就是数组,数组名本身就是一个指针。
#include <iostream>
using namespace std;
int main() {
int a[] = {, , , , };
int *b = a;
cout << a << endl;
cout << b << endl;
return ;
}
运行程序可以看到输出两行一样的地址。
二维数组稍有不同,不同点在于二维数组本身是一个指针数组:
#include <iostream>
using namespace std;
int main() {
int a[][] = {{, , }, {, , }};
int (*b)[] = a;
int *c = a[];
cout << a << " " << b << endl;
cout << *(a + )[] << " " << *(b + )[] << endl;
cout << *c << endl;
return ;
}
b和c的区别在于b是指针数组,包括了(*b)[0]、(*b)[1]、(*b)[2],而c只是一个指针变量,指向数组a的第一个元素的位置。
如图所示:(多维数组同理)

然后我们再看看什么是指针函数。指针函数的定义和指针变量差不多,如
int func1(); // 声明一个函数,返回值为int类型
int *func2(); // 声明一个函数,返回值为int类型指针,指向一个int的地址
我们可以看一个例子:
#include <iostream> using namespace std; // 指针函数
int *square(int &a) {
int *s = new int;
*s = a * a;
return s;
} int square1(int &a) {
int s1 = a * a;
return s1;
} int main() {
int num = ;
cout << "invoke square:" << endl;
cout << *square(num) << endl; // 可以理解为cout << *s << endl;
cout << endl;
cout << "invoke square1:" << endl;
cout << square1(num) << endl;
cout << endl;
return ;
}
上述程序会输出:
invoke square:
25
invoke square1:
25 可以看出,指针函数的用法和指针变量差不多,只不过多了参数(不一定有参数,但函数名后面的括号一定不能漏)
然后我们再看看函数指针,函数指针也是一个指针变量,与普通的指针变量不同的是它指向的是一个函数的地址,如:
#include <iostream> using namespace std; // 指针函数
int *square(int &a) {
int *s = new int;
*s = a * a;
return s;
} int square1(int &a) {
int s = a * a;
return s;
} int main() {
int num = ;
int *(*pSquare)(int &a);
int (*pSquare1)(int &a);
pSquare = square;
pSquare1 = square1;
cout << "invoke square:" << endl;
cout << *(*pSquare)(num) << endl;
cout << endl;
cout << "invoke square1:" << endl;
cout << (*pSquare1)(num) << endl;
cout << endl;
system("pause");
return ;
}
对比一下pSquare和pSquare1我们会发现区别,pSquare是一个指向指针的指针,而pSquare1是一个指向函数的指针,所以pSquare与square搭配,pSquare1与square1搭配。
C++中的指针,指针函数和函数指针的更多相关文章
- C++中怎么获取类的成员函数的函数指针?
用一个实际代码来说明. class A { public: staticvoid staticmember(){cout<<"static"<<endl;} ...
- Keil C51 中的函数指针和再入函数
函数指针是C语言中几个难点之一.由于8051的C编译器的独特要求,函数指针和再入函数有更多的挑战需要克服.主要由于函数变量的传递.典型的(绝大部分8051芯片)函数变量通过堆栈的入栈和出栈命令来传递. ...
- 【编程开发】 C与C++中的关于函数指针的强制类型转换与指针函数的关系
[编程开发] C与C++中的关于函数指针的强制类型转换与指针函数的关系 标签: [编程开发] [VS开发] 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 以 ...
- C语言中指针变量如何向函数中传递
指针变量存储的是地址,所以在函数调用的时候我们能否将指针变量传递给函数?如果不知道结果,那我们可以直接问电脑,输入如下一段代码. void GetMemory(char *p) { p = (char ...
- c++中回调函数和函数指针的使用
#include "stdafx.h" #include <iostream> //#include <string> using namespace st ...
- 区分C语言中的指针函数和函数指针
1.指针函数: 类型说明符 *函数名(形参表) { .......... /*函数体*/ .......... /*函数体*/ } 其中函数名之前加了"*"号表明,这是一 ...
- php中数组模拟队列、栈的函数以及数组指针操作
1,数组指针,current表示当前指针,输出其指向的元素:next表示指针移动到下一个元素:prev指针移动到上一个元素:end表示指针移动到最后一个元素:reset表示指针移动到第一个元素: &l ...
- 12-返回指针的函数&&指向函数的指针
前言 接下来我只讲指针的最常见用法,比如这一章的内容----返回指针的函数 与 指向函数的指针 一.返回指针的函数 指针也是C语言中的一种数据类型,因此一个函数的返回值肯定可以是指针类型的. 返回 ...
- 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)
这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...
随机推荐
- 剑指offer(43)左旋转字符串
题目描述 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S=”abc ...
- error: 'Can't connect to local MySQL server through socket '/data/3307/data/mysql.sock' (2)'
centos7.5 重启mysql报错 问题: [root@db01-51 ~]# mysqladmin -uroot -p123 -S /data/3307/data/mysql.sock shut ...
- WebApi返回的Json去掉XML
在global.asax.cs文件中的 application_start()方法中加入下面一句话 GlobalConfiguration.Configuration.Formatters.XmlFo ...
- MapReduce 踩坑 :Aggregation is not enabled. Try the nodemanager at IP:HOST
原因:yarn-site.xml 中,有关mapreduce日志查看的aggregation未配置启用 解决:在yarn-site.xml 中加入以下配置 <property> <n ...
- 1.6 安全认证与授权(springboot与安全)
引言:以下文档是学习尚硅谷关于springboot教学视频后整理而来! 一.安全 认证(Authentication):证明你是谁? 授权(Authorization):你能干什么? 参考资料: Sp ...
- Yahoo Programming Contest 2019 E - Odd Subrectangles
E - Odd Subrectangles 思路: 对于行方案固定的情况下,假设和为奇数的列为a个,和为偶数的列为b个,a+b = m 那么从奇数里面选奇数个,即C(a, 1) + C(a, 3) + ...
- windows常见软件库
1.护卫神软件库 http://soft.huweishen.com/special/1.html 2.护卫神windows资料库 http://v.huweishen.com/ 3.国超软件下载 h ...
- 在table表格中实现圆角效果
在table中设置border-radius发现不起作用,网上查找了一番,原因是border-collapse:collapse和border-radius不兼容. 设计图效果 代码实现效果: < ...
- MVC模式和MVP模式的区别
MVC模式: 1. MVC的所有通信都是单向的. 2. view传送指令到controller(用户也可以直接将指令传到controller). 3. controller完成业务逻辑后要求model ...
- python报错函数传参数传多了
写python的时候报错: Exception : Traceback (most recent call last): File , in __bootstrap_inner self.run() ...