追了多年的开发框架,你还认识指针吗

2023-3-22 来源:不详 浏览次数:

一:背景

1.讲故事

高级语言玩多了,可能很多人对指针或者汇编都淡忘了,本篇就和大家聊一聊指针,虽然C#中是不提倡使用的,但你能说指针在C#中不重要吗?你要知道FCL内库中大量的使用指针,如String,Encoding,FileStream等等数不胜数,如例代码:

对,你觉得的美好世界,其实都是别人帮你负重前行,退一步说,指针的理解和不理解,对你研究底层源码影响是不能忽视的,指针相对比较抽象,考的是你的空间想象能力,可能现存的不少程序员还是不太明白,因为你缺乏所见即所得的工具,希望这一篇能帮你少走些弯路。

二:windbg助你理解

指针虽然比较抽象,但如果用windbg实时查看内存布局,就很容易帮你理解指针的套路,下面先理解下指针的一些简单概念。

1.、*运算符

取址运算符,用于获取某一个变量的内存地址,*运算符,用于获取指针变量中存储地址指向的值,很抽象吧,看windbg。

仔细观察LOCALS中三组键值对。

1int*ptr=num;=0xb1efff=0xb1efff

int*ptr叫做指针变量,既然是变量必须得有自己的栈上地址0xb1efff,而这个地址上的值为0xb1efff,这不就是num的栈地址嘛,嘿嘿。

2varnum2=*ptr;=0xb1efff=0xa

*ptr就是用ptr的value[0xb1efff]获取这个地址指向的值,所以就是10啦。如果不明白,我画一张图,这可是重中之重哦~

2.**运算符

**也叫二级指针,指向一级指针变量地址的指针,有点意思,如下程序:ptr2指向的就是ptr的栈上地址,一图胜千言。

3.++、--运算符

这种算术操作常常用在数组或者字符串等值类型集合,比如下面代码:

首先ptr默认指向数组在堆上分配的首地址,也就是1的内存地址,当ptr++后会进入到下一个整形元素2的内存地址,再++后又进入下一个int的内存地址,也就是3,很简单吧,我举一个例子:

一图胜千言哈,Console中的三个内存地址分别存的值是1,2,3哈,不过这里要注意的是,C#是托管语言,引用类型是分配在托管堆中,所以堆上地址会存在变动的可能性,这是因为GC会定期回收内存,所以vs编译器需要你用fixed把堆上内存地址固定住来逃过GC的打压,在本例中就是0x001bcaac82da0-(0x001bcaac82da8+4)。

三:用两个案例帮你理解

古语说的好,一言不中,千言无用,你得拿一些例子活讲活用,好吧,准备两个例子。

1.使用指针对string中的字符进行替换

我们都知道string中有一个replace方法,用于将指定的字符替换成你想要的字符,可是C#中的string是不可变的,你就是对它吐口痰它都会生成一个新字符串,的是用指针就不一样了,你可以先找到替换字符的内存地址,然后将新字符直接赋到这个内存地址上,对不对,我来写一段代码,把abcgef替换成abcdef,也就是将g替换为d。

看输出结果没毛病,接下来用windbg去线程栈上找找当前有几个string对象的引用地址,可以在break处抓一个dump文件。

从图中LOCALS中的10个变量地址来看,后面9个有带地址的都是靠近string首

转载请注明:
http://www.wanruiguanye.com/bzff/77435577.html
  • 上一篇文章:

  • 下一篇文章: 没有了
  • 网站首页 版权信息 发布优势 合作伙伴 隐私保护 服务条款 网站地图 网站简介

    温馨提示:本站信息不能作为诊断和医疗依据
    版权所有 2014-2024
    今天是: