C# unsafe code(转)

(*) unsafe 和 fixed

unsafe
{               
    
int [] array  =   new   int [ 10 ];
    
for  ( int  i  =   0 ; i  <  array.Length; i ++ )
    {
        array[i] 
=  i;
    }
    
fixed  ( int *  p  =  array) 
    {
        
for  ( int  i  =   0 ; 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)[ 0 =  (( byte * ) & src)[ 1 ];
            ((
byte * ) & dest)[ 1 =  (( byte * ) & src)[ 0 ];
            
return  dest;
        }

        
public   static  UInt16 ConciseHtons(UInt16 src) 
        {
            UInt16 dest;
            
unsafe
            {
                ((
byte * ) & dest)[ 0 =  (( byte * ) & src)[ 1 ];
                ((
byte * ) & dest)[ 1 =  (( byte * ) & src)[ 0 ];
            }            
            
return  dest;
        }
        
        
static   void  Main() 
        {
            UInt16 val 
=   1 ;

            
//  如果方法是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 
* =   stackalloc  MyClass[ 1 ];  //  Error!! 如果类型要放在托管堆上则不行,如果MyClass是struct就OK了
                p -> val  =   1 ;

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

 

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

原帖:http://www.cnblogs.com/dc10101/archive/2009/03/06/1404586.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值