unsafe关键字相信很多朋友都没有用到过
今天特此来讲一下
1.在unsafe中可以调用指针这是非常重要的一点
1 简单的案例:
static int Main(string[] args) { int i = 0; unsafe { int* ip = &i; Console.WriteLine("scroce i address:{0:x} value:{1}", (int)ip, i); } }
案例过程:
(1) 可以看到我们用一个指针变量ip把 int 类型 i 的指针给存起来了
(2) 然后将其指针 ip 和 i 的值打印了出来
案例结果:
2 string和结构体使用的案例:
struct People { public int Id; unsafe public char* Name; unsafe public char* Remark; } //或 注意类是不能使用的 unsafe struct PeopleTwo { public int Id; public char* Name; public char* Remark; } //主方法 static void Main(string[] args) { string therename = "hb"; string thereRemark = "patter good"; unsafe { //第一部分 开始 fixed(char* charname = therename) { Console.WriteLine("New scroce remark address:0x{0:x} ,And the value is {1}", (int)charname,*charname); } //第一部分 结束 //第二部分 开始 Console.WriteLine("next is People struct"); People per = new People(); per.Id = 4; People* p = &per; fixed (char* twoName = therename, tworemark = therename) { //赋值操作 p->Name = twoName; p->Remark = tworemark; //然后 Console.WriteLine("The struct p address:0x{0:x} ", (int)p); Console.WriteLine("And port 'Name' address is 0x{0:x},value is {1}", (int)p->Name,*p->Name); Console.WriteLine("And port 'Remark' address is 0x{0:x},value is {1}", (int)p->Name, *p->Name); } //第二部分 结束 } }
案例过程:
第一部分:
(1) 首先声明 therename 和 thereRemark 变量
(2) 然后到unsafe不安全块中,定义一个 charname 的字符指针变量进行接收
(3) 然后进行输出 指针地址 与 值
(4)我们可以发现这个值只输出了一个字符,因为这里存储的是 char 类型的指针变量,所以一个指针只对应一个字符
后面会讲如何全部输出!!!
【Note】:fixed 我的理解是让 char* 接收到 string 的特殊方法
第二部分:
(1) 我们声明了一个 People结构体变量 per 并用一个 p 的同结构指针去接收
(2) 然后用 twoName 与 tworemark 字符指针分别去接收 therename 和 thereRemark
(3) 最后赋值给机构 p ,然后对其进行输出
案例结果:
2.处理指针字符变量转string类型
1 在这里我写了一个简单的方法:
static void Main(string[] args) { string therename = "hb"; string thereRemark = "patter good"; unsafe { People per = new People(); per.Id = 4; People* p = &per; SetValue(p, therename, thereRemark); } } unsafe public static void SetValue(People* p, string name, string remark) { fixed (char* therename = name, thereremark = remark) { Console.WriteLine("scroce name address:{0:x}", (int)therename); Console.WriteLine("scroce remark address:{0:x}", (int)thereremark); p->Name = therename; p->Remark = thereremark; Console.WriteLine("new name address:{0:x}", (int)(p->Name)); Console.WriteLine("new remark address:{0:x}", (int)(p->Remark)); string newname = GetString(p->Name); Console.WriteLine($"variable newname value is:{newname}"); string newremark = GetString(p->Remark); Console.WriteLine($"variable newname value is:{newremark}"); } } //处理指针字符变量转string类型 unsafe public static string GetString(char* one) { StringBuilder str = new StringBuilder(); if (one == null) { return ""; } char** text = &one; { while (*text != null) { if (**text == '\0') { break; } str.Append(**text); *text = ++(*text); } } return str.ToString(); }
案例分析:
主要将一下GetString()
首先我要知道字符串是一个字符的数组组成的。
通过 text 二级指针去获取指针变量 one 的指针,循环判断指针是否为空,如果不为空着用 StringBuilder循环添加起来,
当返回值为 '\0' 着表示该指针已经走完了,最后返回结果
案例结果:
3.c/c++扩展
1 maclloc的使用与声明:
People* p2 = stackalloc People[1];
说明:我们知道在 c/c++中,声明动态内存并分配到到站的函数是 maclloc
所以在这里我们可以用 stackalloc 来进行直接创建
如有更多关注请访问:https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/language-specification/unsafe-code
谢谢!
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739