一文搞懂指针,指针的指针,悬浮指针,野指针
一文搞懂指针,指针的指针,悬浮指针,野指针
学习C语言过程中,指针的概念往往是重难点,伴随着时隐时显的*,令人头晕。实际上指针并非如此复杂,掌握最基础概念,有利于我们更深刻的理解指针。
【百科概念】
指针,是C语言中的一个重要概念及其特点,也是掌握C语言比较困难的部分。指针也就是内存地址,指针变量是用来存放内存地址的变量,不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。有了指针以后,不仅可以对数据本身,也可以对存储数据的变量地址进行操作。
【初识指针】
int p=9;
这段代码是非常基础的声明了一个整型变量p,并且赋予初始值为9。当我们在int 后的变量i前加“*”后,就会成为指针变量。
int *p=NULL;
虽然只是一个星号的差距,但本质却发生了巨大变化。int声明的并非i的数据类型,p也并非存储一个int数据类型的值。变量p实际存放的是一个内存“地址”,而int所声明的是这个地址对应内存里存储的数据类型。这点尤为重要,务必彻底搞懂,这是往下理解所必须的,而这里还有一点务必注意,此处的“ * ”属于声明这是一个指针的意思,并非取地址内容的“*”,不要搞混。
接下来将通过一段代码来探索指针的更多性质
int i=9;printf("变量i的地址:0X%x\n",&i);int* p1=NULL;printf("指针p1自己的地址:0X%x\n",&p1);printf("指针p1存放的地址:0X%x\n",p1);p1=&i;printf("指针p1自己现在的地址:0X%x\n",&p1);printf("指针p1存放的地址:0X%x,指针p1存放的地址内的值:%d\n",p1,*p1);
“&”是一个取地址符,代码中,对指针p1的两种输出,“p1” 和 “&p1” 是截然不同的。
直接打印p1将会得到p1实际存储的地址,这个地址起先因为赋予的NULL,所以是0,后面将变量i的地址给P1后,就变成了变量i的地址,运行代码可以发现,“p1” 和 “&i” 的结果是一致的。
当打印“&p1”时,得到的将会是指针p1自身的地址。这里会有点容易混淆,一个指针怎么出现了两个地址?指针变量本身也是一种变量,也需要内存空间来存储一个值,只不过这个值不同于int,double,char等,而是一个代表特定内存位置的“门牌号”。所以针对指针p1我们确实可以得到两个地址,一个是自己的,一个是别人的。
而地址与我们而言并没有太多的实际意义,我们关心的从来不是冰冷的地址字符串,而是他所对应内存中所存储的实际内容。基于这个需求,“*”又再次出现了。当我们打印 “*p1” 时,将会得到变量i的值。
同时还会注意到,对指针p1的不同赋值,并不会影响到“&p1”的结果,这其实是必然的,毕竟指针自己的地址是不会随着他所存储内容的变化而改变的,就像住房的地址不因入住人的改变而改变一样。
下面是上面代码的输出,不同机器,实际的地址是不同的。
变量i的地址:0Xefbff4fc
指针p1自己的地址:0Xefbff4f0
指针p1存放的地址:0X0
指针p1自己现在的地址:0Xefbff4f0
指针p1存放的地址:0Xefbff4fc,指针p1存放的地址内的值:9
对指针赋值时,如下两种方式,区别是什么呢?
int i=0;
int *p=&i;
//1
*p=5;
//2
p=5
代码1是对指针p所指向地址实际内容的修改,而代码2是对指针本身的修改,让他存储了一个新地址,实际上这样的赋值是非法的,应该是
p=&变量;
或
p=p2(p2是另一个指针)
【指针的指针】
指针的指针,顾名思义,是一个指针存放的地址是另外一个指针。实际上像一个“套娃”。他的声明形式是
int **p2=NULL;
如果你想定义一个指针的指针的指针
int ***p2=NULL;
…
以此类推,我们主要研究指针的指针,为他赋值:
int **p2=NULL;p2=&p1;
这里的p1是上文指向变量i的p1。
当有两个“*”时,我们还是逐层为他“脱衣”,看看会输出怎样的结果
//定义指针的指针int **p2=NULL;p2=&p1;printf("p2自身的地址:0X%x,p2存放的地址:0X%x, p1指针存放的地址:0X%x,p2存放指针指向的地址实际的值:%d\n,",&p2,p2,*p2,**p2);
输出:
p2自身的地址:0Xefbff4e0,p2存放的地址:0Xefbff4f0, p1指针存放的地址:0Xefbff4fc,p2存放指针指向的地址实际的值:9
换句话说:
“&p2”是指针变量p2 自己 的地址。
“P2” 是p2存储的地址,这里等价于“&p1”
“*p2”是p1所存放的地址,等价于&i
“**p2”是p1存放地址对应内存实际的内容,等价于直接打印变量i
【野指针】
当一个指针未初始化时,他的指向是不确定并且危险的,所以称之为“野指针”,如下便是一个“野指针”
//野指针int *n;
【悬浮指针】
当一个指针指向的内存被释放时,却没有对指针赋NULL时,这个指针就是悬浮指针。试想别人昨天给了你一个住址,今天他家拆迁搬走了,但却没告诉你,而你明天去了会有怎样的结果!换到程序这里可能引起软件和系统的崩溃。
如下是一个悬浮指针:
//悬浮指针void *x=malloc(1024);free(x);
【指针简单应用】
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {// insert code here...int i=0;ChangeI(i);printf("(changeI)i的值:%d\n",i);}
void ChangeI(int i){i=123;
}
上面的输出是多少呢?答案是123.这当然是不对的!答案是0,因为实参与形参是不同的内存空间,函数参数的传递也仅仅只是值的传递。那要如何才能改变i呢?用指针即可!
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {// insert code here...int i=0;ChangeII(&i);printf("(changeII)i的值:%d\n",i);}
void ChangeII(int *i){*i=123;
}
上述结果就是123了。
一文搞懂指针,指针的指针,悬浮指针,野指针相关推荐
- ES6学习——一文搞懂ES6
ES6学习--一文搞懂ES6 es6介绍 ES全称EcmaScript,是脚本语言的规范,而平时经常编写的EcmaScript的一种实现,所以ES新特性其实就是指JavaScript的新特性. 为什么 ...
- 一文搞懂 MySQL 索引
一文搞懂 MySQL 索引 1.MySQL 索引 简介 1.1.MySQL 索引 是什么? 索引是一个单独的.存储在 磁盘 上的 数据库结构 ,包含着对数据表里 所有记录的 引用指针. 1.2. M ...
- 悬垂指针(Dangling pointer)和野指针(Wild pointer)
转自:http://www.cnblogs.com/submarine/archive/2013/03/02/2940169.html 参看维基百科: Dangling pointer 迷途指针 == ...
- 一文搞懂RNN(循环神经网络)
基础篇|一文搞懂RNN(循环神经网络) https://mp.weixin.qq.com/s/va1gmavl2ZESgnM7biORQg 神经网络基础 神经网络可以当做是能够拟合任意函数的黑盒子,只 ...
- c6011取消对null指针的引用_C++中的野指针及其规避方法
今天在调试程序过程中,用到了一些指针的方法,这里记录一下野指针的概念. 1.概念 野指针,也就是指向不可用内存区域的指针.通常对这种指针进行操作的话,将会使程序发生不可预知的错误. 野指针与空指针(N ...
- 一文搞懂 Python 的 import 机制
一.前言 希望能够让读者一文搞懂 Python 的 import 机制 1.什么是 import 机制? 通常来讲,在一段 Python 代码中去执行引用另一个模块中的代码,就需要使用 Python ...
- python语言语句快的标记是什么_一文搞懂Python程序语句
原标题:一文搞懂Python程序语句 程序流 Python 程序中常用的基本数据类型,包括: 内置的数值数据类型 Tuple 容器类型 String 容器类型 List 容器类型 自然的顺序是从页面或 ...
- 一文搞懂 Java 线程中断
转载自 一文搞懂 Java 线程中断 在之前的一文<如何"优雅"地终止一个线程>中详细说明了 stop 终止线程的坏处及如何优雅地终止线程,那么还有别的可以终止线程 ...
- 一文搞懂HMM(隐马尔可夫模型)-Viterbi algorithm
***一文搞懂HMM(隐马尔可夫模型)*** 简单来说,熵是表示物质系统状态的一种度量,用它老表征系统的无序程度.熵越大,系统越无序,意味着系统结构和运动的不确定和无规则:反之,,熵越小,系统越有序, ...
最新文章
- 网络安全模型_基于TCM的网络安全访问模型
- jQuery - 设置内容和属性
- Shiro在SpringBoot中的应用
- hdu 3853 LOOPS 概率DP
- 查看运行时间_怎样查看自己电脑系统的版本信息?
- [react] Mern和Yeoman脚手架有什么区别?
- PostgreSQL的核心架构
- 扑捉和捕捉的区别照相_扑捉和捕捉的区别照相
- [CF671E] Organizing a Race
- mysql查询临时表是否存在_[转]SQL判断临时表是否存在
- php bc gmp,php中ipv6转纯数字和反转
- python random 之基础点名器
- ArcGIS制图(一)之流向图
- JAVA实现中点画线_Java 实现中点法画线
- 如何利用python中的pandas模块计算环比和同比
- igraph基本使用方法示例
- 智能管家---4.Log封装
- S7-1200PLC 与温控仪表Modbus RTU通信
- ThreadPoolExecutor(五)——线程池关闭相关操作
- python笔试题110题_吐血整理:110道python面试题(带答案)