一:背景
1. 讲故事
高级语言玩多了,可能很多人对指针或者汇编都淡忘了,本篇就和大家聊一聊指针,虽然C#中是不提倡使用的,但你能说指针在C#中不重要吗?你要知道FCL内库中大量的使用指针,如String,Encoding,FileStream等等数不胜数,如例代码:
private unsafe static bool EqualsHelper(string strA, string strB)
{
fixed (char* ptr = &strA.m_firstChar)
{
fixed (char* ptr3 = &strB.m_firstChar)
{
char* ptr2 = ptr;
char* ptr4 = ptr3;
while (num >= 12) {...}
while (num > 0 && *(int*)ptr2 == *(int*)ptr4) {...}
}
}
}
public unsafe Mutex(bool initiallyOwned, string name, out bool createdNew, MutexSecurity mutexSecurity)
{
byte* ptr = stackalloc byte[(int)checked(unchecked((ulong)(uint)securityDescriptorBinaryForm.Length))]
}
private unsafe int ReadFileNative(SafeFileHandle handle, byte[] bytes, out int hr)
{
fixed (byte* ptr = bytes)
{
num = ((!_isAsync) ? Win32Native.ReadFile(handle, ptr + offset, count, out numBytesRead, IntPtr.Zero) : Win32Native.ReadFile(handle, ptr + offset, count, IntPtr.Zero, overlapped));
}
}
对,你觉得的美好世界,其实都是别人帮你负重前行,退一步说,指针的理解和不理解,对你研究底层源码影响是不能忽视的,指针相对比较抽象,考的是你的空间想象能力,可能现存的不少程序员还是不太明白,因为你缺乏所见即所得的工具,希望这一篇能帮你少走些弯路。
二:windbg助你理解
指针虽然比较抽象,但如果用windbg实时查看内存布局,就很容易帮你理解指针的套路,下面先理解下指针的一些简单概念。
1. &、* 运算符
&取址运算符,用于获取某一个变量的内存地址, *运算符,用于获取指针变量中存储地址指向的值,很抽象吧,看windbg。
unsafe
{
int num1 = 10;
int* ptr = &num1;
int** ptr2 = &ptr;
var num2 = **ptr2;
}
0:000> !clrstack -l
ConsoleApp4.Program.Main(System.String[]) [C:dreamCsharpConsoleApp1ConsoleApp4Program.cs @ 26]
LOCALS:
0x000000305f5fef24 = 0x000000000000000a
0x000000305f5fef18 = 0x000000305f5fef24
0x000000305f5fef10 = 0x000000305f5fef18
0x000000305f5fef0c = 0x000000000000000a
2. **运算符
** 也叫二级指针,指向一级指针变量地址的指针,有点意思,如下程序:ptr2指向的就是 ptr的栈上地址, 一图胜千言。
unsafe
{
int num1 = 10;
int* ptr = &num1;
int** ptr2 = &ptr;
var num2 = **ptr2;
}
0:000> !clrstack -l
ConsoleApp4.Program.Main(System.String[]) [C:dreamCsharpConsoleApp1ConsoleApp4Program.cs @ 26]
LOCALS:
0x000000305f5fef24 = 0x000000000000000a
0x000000305f5fef18 = 0x000000305f5fef24
0x000000305f5fef10 = 0x000000305f5fef18
0x000000305f5fef0c = 0x000000000000000a










