(*) unsafe 和 fixed


unsafe

{               

    int[] array = new int[];

    for (int i = ; i < array.Length; i++)

    {

        array[i] = i;

    }

    fixed (int* p = array) 

    {

        for (int i = ; i < array.Length; i++)

        {

            System.Console.WriteLine(p[i]);

        }                    

    }               

}

指针在c#中是不提倡使用的,有关指针的操作被认为是不安全的(unsafe)。因此运行这段代码之前,先要改一个地方,否则编译不过无法运行。
修改方法:在右侧的solution Explorer中找到你的项目,在项目图标(绿色)上点右键,选最后一项properties,然后在Build标签页里把Allow unsafe code勾选上。之后这段代码就可以运行了,你会看到,上面这段代码可以像C语言那样用指针操纵数组。但前提是必须有fixed (int* p = array),它的意思是让p固定指向数组array,不允许改动。因为C#的自动垃圾回收机制会允许已经分配的内存在运行时进行位置调整,如果那样,p可能一开始指的是array,但后来array的位置被调整到别的位置后,p指向的就不是array了。所以要加一个fixed关键字,把它定在那里一动不动,之后的操作才有保障。

另有两点需要注意:

1)指针的使用必须放在unsafe的区域里;unsafe关键字也可作为类或方法的修饰符。

2)fixed (int* p = array)中,p的定义不能写在别处,而且fixed关键字也只能在unsafe区域里使用。

(*) 略简洁的unsafe写法


    class Program

    {

        unsafe public static UInt16 Htons(UInt16 src) 

        {

            UInt16 dest;

            // 不能照搬C的源代码,因为有些类型长度不一样,如char(2字节),long(8字节)

            // ((char*)&dest)[0] = ((char*)&src)[1];

            // ((char*)&dest)[1] = ((char*)&src)[0];

            ((byte*)&dest)[] = ((byte*)&src)[];

            ((byte*)&dest)[] = ((byte*)&src)[];

            return dest;

        }

        public static UInt16 ConciseHtons(UInt16 src) 

        {

            UInt16 dest;

            unsafe

            {

                ((byte*)&dest)[] = ((byte*)&src)[];

                ((byte*)&dest)[] = ((byte*)&src)[];

            }            

            return dest;

        }

        

        static void Main() 

        {

            UInt16 val = ;

            // 如果方法是unsafe的,则必须在unsafe block里调用

            unsafe

            {                

                val = Htons(val);

            }

            Console.WriteLine(val);

            // 更简洁的写法是把unsafe block写在函数内部

            val = ConciseHtons(val);

            Console.WriteLine(val);

        }                

    }

(*) stackalloc

stackalloc的用处仅仅是把数组分配在栈上(默认是分配在托管堆上的)。


    class MyClass

    {

        public int val;

    }

    class Program

    {                

        static void Main() 

        {            

            unsafe

            {                

                MyClass *p = stackalloc MyClass[]; // Error!! 如果类型要放在托管堆上则不行,如果MyClass是struct就OK了

                p->val = ;

                int *iArray = stackalloc int[];  // OK,在栈上创建数组, int类型本身就是放在栈上的

            }            

        }                

    }

注意:指针指向的内存一定要固定。凡是C#里的引用类型(一切类型的数组都是引用类型)都是分配在托管堆上的,都不固定。有两种方法强制固定,一种是用stackalloc分配在栈上,另一种是用fixed分配在堆上。

C# unsafe code的更多相关文章

  1. C#基础—不安全代码(unsafe code)

    1.为何要有unsafe 也许是为了实现CLR类型安全的目标吧,默认情况下,C#没有提供指针的使用算法,但是有些情况下也可能需要指针这样直接访问内存的东西(虽然目前我还没有用过),但是有时候程序员非常 ...

  2. 发布web应用程序是出现unsafe code

    找到了解决办法 解决方法参照: https://stackoverflow.com/questions/16567197/publish-web-application-with-unsafe-cod ...

  3. Unity3D 使用C#指针unsafe

    Unsafe code requires the `unsafe' command line option to be specified 在Unity开发中,如果涉及到指针的使用,需要自己定义预处理 ...

  4. Unity3d中C#使用指针(Unsafe)的办法(转)

    近日由于在U3D项目中要使用到数据传递(C++ DLL的数据传递给U3D中的C#),其中涉及到需要使用C#的指针.直接编译会出现以下错误Unsafe code requires the 'unsafe ...

  5. Java中Unsafe类详解

    http://www.cnblogs.com/mickole/articles/3757278.html Java不能直接访问操作系统底层,而是通过本地方法来访问.Unsafe类提供了硬件级别的原子操 ...

  6. java 非阻塞算法实现基础:unsafe类介绍

    一.为什么要有Unsfae.我们为什么要了解这个类 1. java通常的代码无法直接使用操作底层的硬件,为了使java具备该能力,增加了Unsafe类 2.java的并发包中底层大量的使用这个类的功能 ...

  7. JAVA中神奇的双刃剑--Unsafe

    前提 参考资料: Java魔法类:sun.misc.Unsafe 在openjdk8下看Unsafe源码 Unsafe介绍 在Oracle的Jdk8无法获取到sun.misc包的源码,想看此包的源码可 ...

  8. Understanding sun.misc.Unsafe

    转自: https://dzone.com/articles/understanding-sunmiscunsafe The biggest competitor to the Java virtua ...

  9. Code Project精彩系列(转)

    Code Project精彩系列(转)   Code Project精彩系列(转)   Applications Crafting a C# forms Editor From scratch htt ...

随机推荐

  1. LeetCode_Wildcard Matching

    Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single character. ...

  2. haproxy简单负载均衡搭建

    最近对负载均衡进行搭建具体方法如下: haproxy 修改部分(haproxy-cfg.cfg) global daemon maxconn 4500 defaults mode http timeo ...

  3. ubuntu下安装Apache+PHP+Mysql(转)

    转载自:http://www.comflag.com/2011/05/01/apache-web.htm 步骤一,安装apache2 1 sudo apt-get install apache2 安装 ...

  4. Lua Interface基础使用

    Lua是一种可爱的脚本语言,由Roberto Ierusalimschy.Waldemar Celes 和 Luiz Henrique de Figueiredo所组成并于1993年开发. 其设计目的 ...

  5. ios block使用

    BlockTest.h #import <Foundation/Foundation.h> typedef void (^didFinishBlock)(NSString *str); t ...

  6. Mac截屏快捷键总结

    Mac截屏快捷键总结 1)Command-Shift-3: 将整个屏幕拍下并保存到桌面. 2)Command-Shift-Control-3:     将整个屏幕拍下并保存到剪贴板(Clipboard ...

  7. Block内的强引用

    众所周知,当某个对象持有着一个Block的时候,如果在Block内部使用强引用反过来持有这个对象,就会导致引用循环.为了避免引用循环,可以使用__weak修饰符,苹果的官方文档在用代码演示__weak ...

  8. Linux正則表達式-反复出现的字符

    星号(*)元字符表示它前面的正則表達式能够出现零次或多次.也就是说,假设它改动了单个字符.那么该字符能够在那里也能够不在那里,而且假设它在那里,那可能会不止出现一个.能够使用星号元字符匹配出如今引號中 ...

  9. EffectiveC#17--装箱和拆箱的最小化

    1.如下这段代码会经历装箱和拆箱.例如25会先装箱成object后传递给writeline方法(一次拷贝),在方法内部又 经历拆箱成int(第二次拷贝)后然后调用tostring(). Console ...

  10. Android-------手机屏幕适配之文件适配

    public class Main {         //定义文件本地存储路径,可按照需求更改         private final static String rootPath = &quo ...