C语言-指针
C指针基础知识
C语言中,指针无疑是最令人头疼的。今天无事就来学学C语言的指针,在此留下点笔记,仅供个人参考。
首先要搞懂的是,指针是什么?
指针:是用来存放内存地址的变量。
不管是什么类型的指针,存放的都是内存地址,所有类型的指针变量的大小都是一致的。
和指针相关的两个符号: & 取址符。取一个变量的地址。 * 表示一个指针,同时也可以取指针对应的变量的值。
下面来看一下指针最简单的使用。
代码上解释的比较清楚了,来看看打印的结果,前两行打印的结果是一样的,所以可以看出,指针里面存放的就是变量i的地址。
看打印结果的后面两行,可以看出。这两行的结果都是3,倒数第二行打印出来的就比较好理解了,是变量i的值,也就是3;打印结果的最后一样,也是3,*pi 表示取指针变量 pi 存储的地址所对应的变量的值。
说起来有点绕,反正,记住,指针是地址,而 *pi 是取值,取该指针对应的变量的值。
这个例子中,有一点需要明白的是:不论改变i的值还是 pi 的值,都不会互相影响。
也就是说,改变了i的值,pi 的值是不会变的,这个好理解,我只是改变了这个变量的值,而我这个变量依然在内存中,还是在那块内存中,所以,只要这i的在内存中的位置(地址)不变,pi 的值就不会变。
同时,改变了 pi 的值,i 的值也是不会变的,例如现在多了一个 int 类型的 j 变量,然后把 j 变量的地址赋给 pi,那么只是改变了 pi 的值,pi 里面存放的是变量j的地址,而变量i的地址和值都不会发生任何改变。
这也就是指针的灵活性,指针可以指向该指针对应的类型的任意变量。(说白了就是 --> pi 能指向任何 int 类型的变量,不能指向其他类型的变量)
下面再来看一个简单的例子,交换两个数字。
如果不使用指针的话,很简单,直接搞一个中间变量,就可以交换这两个变量的值了。而使用指针的话,也很简单,照葫芦画瓢嘛。
上面注释掉的是不用指针的时候,一清二楚,不用说都明白了。
下面是使用指针的情况,都说照葫芦画瓢了,既然指针 pi 存放的是变量 i 的地址,那么,*pi 就表示变量 i 的值,那么就好办了,在前面的代码中,用 *pi 替代掉 i 不就好了么,同样的道理,用 *pj 替代掉 j 就好了。
最后来看一下下面两个方法,这两个方法是一点更要搞懂的,不然你说我知道什么是指针。那就是扯蛋。
假设我现在不在主函数里面交换两个变量 i j 的值,而是调用一个方法去交换他们的值,现在该调用哪个方法呢?
很简单嘛,两个都一样,既然传进去的是int类型的值,那么就直接取指针变量对应的值不就得了,也就是这样:swap( *pi , *pj );
而调用第二个的时候就是 swap( pi , pj );
没错,方法调用是没错的,是这样调用。但能够使值交换的,只有下面这个方法,道理也很简单:
先看上面方法那个代码,方法体中的 x y 都是局部变量,这个方法改变的只是局部变量的值。而主函数里面的确没有改变。所以,这个函数是不能交换其值的.(这也就是值传递)
再来看下面这个方法,下面这个方法是可以,下面方法为什么可以呢?因为传递的是地址。为啥传递的地址就可以?
这个嘛,举个例子。怎么举例呢?居然这个涉及到了内存,那么就举一个看起来吻合一点的例子吧!
有两个房子,地址分别是人民路1号和人民路8号,1号房子里面存放着一个篮球,8号房子里面存放着一个足球。
第一个方法,就好像直接把球复制出来。把复制品去交换,也就是值得传递,而第二个方法则传的是两个房子的地址,跟你说要把两个房子里面的球交换一下。然后你就跑去1号房子,把球抱出来,然后跑到8号房子,交换球,再把球拿回到1号房子。就这么简单。这就是引用传递。
小结:
如何让子函数更改主函数的值?
1:子函数的形参为一个地址的值。
2:子函数去修改形参的地址所对应的变量的值。
3:主函数在使用的时候把要修改的变量的值传递给子函数。
指针常见的错误:
1:指针变量在没有赋值之前不能使用。
没有赋值,也就是垃圾值,在编程上就叫野指针;
2:类型不同的指针不能互相转换。
3:使用指针的时候,不去访问已经被系统回收的数据。
子函数执行完毕后,子函数的所有局部变量都会被系统回收,如果能够获取到值,那都是影子值,是不能确保该值的正确性;
指针还有一个比较灵活的使用,在java中,返回值可以是基本类型,也可以是对象,也可以容器类(数组,集合等),但在C中是不允许返回数组的。那么,我们使用指针可以返回2个以上的参数。
怎么返回呢?很简单啊,既然容器类可以装多个变量,而C中是没有集合的,那就是数组了呗,数组又要返回一个,怎么返回呢?直接返回数组的地址不就好了么!
指针的运算:
指针其实也可以像其他变量一样运算。
开什么玩笑,指针也可以计算,指针不是地址么?两个地址运算的结果是什么?例如拿上面那个例子,人民路1号和人民路8号,运算的结果是啥?难道是人民路9号?
没错,你说对了,指针当然不能直接的使用地址进行加减乘除,地址的加减乘除是没有任何意义也不允许这样子做的。
既然不能使用指针去进行加减乘除,那么我们在每一个指针前面加个*,也就是取指针的值进行运算不就得了,没错,这也是对的。
但;这是指针的运算么,这是指针所对应的值的运算,好吧!
既然说是指针的运算,那就是指针的运算,来看下面这个例子:
这个就是一个指针运算的例子,看最后两行的打印语句,变量i不就是指针变量么,指针变量+1和-1不就是指针的运算么?
可以看到的是:打印的第一行,取指针 i 所对应的值,也就是数组arr下标为2的值(数组中第三个,也就是3).
上面这点搞明白了就好办了,指针+1和-1表示取这个指针变量相邻的地址所对应的值。这句话怎么理解呢?也就是说,+1表示取这个位置的下一个,而-1表示取上一个,这个比较好理解。
但它是怎么取得呢?怎么去识别的呢?一个int里面是4个字节。是怎么会自动的向上或向下偏移4个字节的呢?
别忘了,指针也是有数据类型的,虽然指针里面存放的都是地址,但这个地址只能存该指针相对应的变量的地址,所以,指针在运算偏移的时候就会根据指针自身对应的变量的长度来进行偏移。
多级指针
说白了,就是指针的指针,其中可以有N层,哈哈。
假设有这样一段代码:
int i=5;
int* pi=&i;
int** ppi=π
第一行很好理解了,第二行我们也知道是什么意思了,接下来看第三行;
第三行就是指针的指针,也就是说,里面存放的是指针的地址,这个怎么理解呢,第二行很好理解吧,指针变量存放的是 int 类型变量i的地址,同样的道理,既然变量i是在内存中存在的,那么变量 pi 也是在内存中实际存在的,所以,变量 pi 也是有地址的,这里存放的就是指针 pi 的地址。其实就好像你去找人,我要去找张三,结果我去到教室。张三不在,同学说张三去了宿舍(一级指针),然后我跑会宿舍,同学说张三在饭堂(二级指针)。如果饭堂没找到,那就是三级指针了。哈哈
这个搞清楚了,接下来就好办了。还是上面这个例子:
pi 里面存放的变量i的地址,那么,*pi 就是取变量i的值,而ppi存放的是 pi 的地址,那么 *ppi 其实取到的就是 pi 的值(变量i的地址),那么要通过 ppi 去取变量i的值,那么就要使用 **ppi 了。这个比较好理解,上面这个理解清楚下面的就好理解了。
最后说一点:函数的指针
指针不仅可以是变量的指针,指针的指针,还可以是函数的指针。同理,函数的指针存放的是个函数的地址。
看代码:
这就是一个函数的指针的简单的示例代码,代码里面注释也写的比较清楚了。
这里需要注意的是,函数必须写在main函数之前,因为函数必须要先装载进内存,才能知道函数的地址是啥,否则会报错。
指针基础只是就写到这里:
2016-10-18 21:30
C语言-指针的更多相关文章
- C语言指针转换为intptr_t类型
1.前言 今天在看代码时,发现将之一个指针赋值给一个intptr_t类型的变量.由于之前没有见过intptr_t这样数据类型,凭感觉认为intptr_t是int类型的指针.感觉很奇怪,为何要将一个指针 ...
- [转]C语言指针学习经验总结浅谈
指针是C语言的难点和重点,但指针也是C语言的灵魂 . 这篇C语言指针学习经验总结主要是我入职以来学习C指针过程中的点滴记录.文档里面就不重复书上说得很清楚的概念性东西,只把一些说得不清楚或理解起来比较 ...
- 不可或缺 Windows Native (7) - C 语言: 指针
[源码下载] 不可或缺 Windows Native (7) - C 语言: 指针 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 指针 示例cPointer.h #i ...
- C语言指针学习
C语言学过好久了,对于其中的指针却没有非常明确的认识,趁着有机会来好好学习一下,总结一下学过的知识,知识来自C语言指针详解一文 一:指针的概念 指针是一个特殊的变量,里面存储的数值是内存里的一个地址. ...
- (转载)c语言指针学习
前言 近期俄罗斯的陨石.四月的血月.五月北京的飞雪以及天朝各种血腥和混乱,给人一种不详的预感.佛祖说的末法时期,五浊恶世 ,十恶之世,人再无心法约束,道德沦丧,和现在正好吻合.尤其是在天朝,空气,水, ...
- 关于C语言指针的问题
在学习关于C语言指针的时候,发现这样一个问题,代码如下: #include<stdio.h> #include<stdlib.h> #include<string.h&g ...
- C语言指针类型 强制转换
关于C语言指针类型 强制转换 引用一篇文章: C语言中,任何一个变量都必须占有一个地址,而这个地址空间内的0-1代码就是这个变量的值.不同的数据类型占有的空间大小不一,但是他们都必须有个地址,而这个 ...
- C语言指针和数组知识总结(上)
C语言指针和数组知识总结(上) 一.指针的基础 1.C语言中,变量的值能够通过指针来改变,打印指针的语句符号可以是: %08x 2.指针的本质 指针的本质就是变量,那么既然是变量,那么一定会分配地址 ...
- C语言指针操作
欢迎访问我的新博客:http://www.milkcu.com/blog/ 原文地址:http://www.milkcu.com/blog/archives/pointer-manipulation. ...
- C语言指针声明探秘
C语言指针声明探秘
随机推荐
- Ubuntu14.04 CUDA8.0 CUDN4.0 NVIDIA1080 多种深度框架(懒人三步装) - 从入门到放弃
这是一个懒人快速安装教程,1080卡有点麻烦,因为cuda需要8.0.为了安装方便直接把命令写成三个shell脚本. 代码基本是http://blog.csdn.net/langb2014/artic ...
- JFreeChart
花了四个小时给同学写的.还行吧,原来都没有用过到处找资料写的. package DrawLine; import org.jfree.chart.ChartFactory; import org.jf ...
- 转:Webpack 指南(整理 草稿)
基础 安装 首先要安装 Node.js, Node.js 自带了软件包管理器 npm.用 npm 全局安装 Webpack: $ npm install webpack -g 通常我们会将 Webpa ...
- javaFx:使用弹出对话框 Alert
javaFx8 自带的对话框非常好用,类似的使用方式如下: /** * 弹出一个通用的确定对话框 * @param p_header 对话框的信息标题 * @param p_message 对话框的信 ...
- Java jvisualvm简要说明
jvisualvm能干什么:监控内存泄露,跟踪垃圾回收,执行时内存.cpu分析,线程分析... jvisualvm已经被集成在jdk1.6以上的版本中(不是jre).自身运行需要最低jdk1.6版本, ...
- @Autowired
1. Spring框架中进行注入式,使用@Autowired. @Autowired可以对成员变量.方法和构造函数进行标注,来完成自动装配的工作,这里必须明确:@Autowired是根据类型进行自动装 ...
- 基于黑名单的xss过滤器
/** * 类名称:AntiXssFilter * @version * 类描述:基于黑名单的xss过滤器 * @version * 创建人:xxx * @version * 创建时间:2015年11 ...
- Log4Net异常日志记录在asp.net mvc3.0的应用
前言 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.本文主要是简单的介绍如何在Visual ...
- BOM DOM Event事件笔记....
js//获取文件标题 document.body //body document.title //网页标题 document.doctype//文档对象 document.url//路径 //服务器相 ...
- Hello Bugs
2014-01-09 [Maven]Not Authorized ReasonPhame: Failed to decrypt password... 描述:eclipse中使用maven进行mvn ...