浅谈C#固定的和活动的变量

开发 后端
本文介绍C#固定的和活动的变量,以及介绍在不安全上下文中,一个表达式的值可以来自于一个指针类型;但是在上下文之外,会造成编译时期错误。

C#固定的和活动的变量

&和fixed将变量分为两类:C#固定的和活动的变量。

固定的变量***的存在并不会被GC的操作影响。(例如局部变量,值参数和间接指针)活动的变量会被GC重新分配位置或是释放(例如对象中的字段,基础数据数组)。

&取固定变量的地址是没有限制的。但是活动变量容易受GC的影响,其地址只能通过fixed来获得,并且地址仅会在整个fixed语句的周期持续有效。

静态字段也是活动变量。还有标记为ref或out的也是活动变量,即使这个参数是传递给固定参数的。***,通过间接指针引用的变量总是固定变量。

指针转换

在不安全上下文中,下面的转换是隐式的:
◆从任何指针类型到void*
◆从null到任何指针类型

除此之外,下面的转换都是显式的:
◆从任何指针类型到另外的指针类型
◆从sbyte, byte, short, ushort, int, uint, long, or ulong到其他类型
◆从任何类型到sbyte, byte, short, ushort, int, uint, long, or ulong

指针转换并不改变指针的值。也就是说指针转换前后不影响地址的值。

当转换发生后,当结果指针没有按照正确的指针类型排列的话,当访问结果时结果是无法预知的。

下面的例子:

  1. char c = 'A';  
  2. char* pc = &c;  
  3. void* pv = pc;  
  4. int* pi = (int*)pv;  
  5. int i = *pi;  
  6. // undefined  
  7. *pi = 123456;  
  8. // undefined 

下面的例子会打印出double的8字节的值:

  1. usingSystem;  
  2. classTest  
  3. {  
  4. unsafestaticvoidMain(){  
  5. doubled=123.456e23;  
  6. unsafe{  
  7. byte*pb=(byte*)&d;  
  8. for(inti=0;i<sizeof(double);++i)  
  9. Console.Write("{0:X2}",*pb++);  
  10. Console.WriteLine();  
  11. }  
  12. }  

打印结果取决于endian.

指针数组

在不安全上下文中,是允许指针数组的,只有几种用于其转换是允许的:
◆从任何数组类型到System.Array或是实现了其接口的隐式引用类型转换同样适用于指针数组。但是,任何试图通过System.Array或是实现了其接口访问数组元素都会引发一个 运行时错误,因为指针类型不能转化为object.
◆从一个一维数组类型S[]到System.Collections.Generic.IList<T>或是到其基接口,任何显示或是隐式的转换都是不行的。因为指针类型不能被用作类型参数,还有没有从指针类型到非指针类型的转换。
◆从System.Array或是实现了其接口到任何数组类型显示引用转换适用于指针数组。
◆从System.Collections.Generic.IList<T>或是到其基接口到一个一维数组类型T[],任何显示的转换都是不行的。原因同上面第2条。

还有就是对于foreach语句,不适用于指针数组。相反,下面的语句

foreach (V v in x) embedded-statement

中的x是一个数组类型T[,,…,],n是数组的维度减1,T和V是指针类型,被改写为:

  1. {  
  2. T[,,…,]a=x;  
  3. Vv;  
  4. for(inti0=a.GetLowerBound(0);i0<=a.GetUpperBound(0);i0++)  
  5. for(inti1=a.GetLowerBound(1);i1<=a.GetUpperBound(1);i1++)  
  6. …  
  7. for(intin=a.GetLowerBound(n);in<=a.GetUpperBound(n);in++){  
  8. v=(V)a.GetValue(i0,i1,…,in);  
  9. embedded-statement  
  10. }  

变量a,i0,i1,…对于x或者embedded-statement或者其余部分的代码是不可见的或是不可访问的。变量v在embedded-statement中是只读的。如果没有显示转换从T到V,那么就会有错误。如果x是个null,就会有空引用异常。

表达式中的指针

在不安全上下文中,一个表达式的值可以来自于一个指针类型;但是在上下文之外,会造成编译时期错误。

间接访问

一元的*表示一个指针,被用来获得指针指向的值。*用在void*类型表达式或是非指针类型表达式时,会造成编译期错误。

*被用在null指针时是由实现来决定的。不能保证在使用时会抛出System.NullReferenceException.

如果一个非法的值赋给指针,那么*的行为是不可预知的。

指针成员访问

在指针成员访问P->I中,P必须是除了void*之外的类型,I同时必须是一个可访问的成员。

P->I效果上相同于(*P)。I.例如:

  1. usingSystem;  
  2. structPoint  
  3. {  
  4. publicintx;  
  5. publicinty;  
  6. publicoverridestringToString(){  
  7. return"("+x+","+y+")";  
  8. }  
  9. }  
  10. classTest  
  11. {  
  12. staticvoidMain(){  
  13. Pointpoint;  
  14. unsafe{  
  15. Point*p=&point;  
  16. p->x=10;  
  17. p->y=20;  
  18. Console.WriteLine(p->ToString());  
  19. }  
  20. }  

或是

  1. classTest  
  2. {  
  3. staticvoidMain(){  
  4. Pointpoint;  
  5. unsafe{  
  6. Point*p=&point;  
  7. (*p).x=10;  
  8. (*p).y=20;  
  9. Console.WriteLine((*p).ToString());  
  10. }  
  11. }  

指针元素访问

在指针元素访问P[E]中,P必须是除了void*之外的类型,同时E必须能隐式的转换为int, uint, long, or ulong的表达式。

P[E]效果上同*(P + E)。例如:

  1. classTest  
  2. {  
  3. staticvoidMain(){  
  4. unsafe{  
  5. char*p=stackallocchar[256];  
  6. for(inti=0;i<256;i++)p[i]=(char)i;  
  7. }  
  8. }  
  9. }  
  10. 又如:  
  11. classTest  
  12. {  
  13. staticvoidMain(){  
  14. unsafe{  
  15. char*p=stackallocchar[256];  
  16. for(inti=0;i<256;i++)*(p+i)=(char)i;  
  17. }  
  18. }  

以上介绍C#固定的和活动的变量

【编辑推荐】

  1. C#调用Windows API函数
  2. 详解C#调用Outlook API
  3. C#连接Access、SQL Server数据库
  4. 介绍C#调用API的问题
  5. C#调用Excel与附加代码
责任编辑:佚名 来源: IT168
相关推荐

2009-08-13 15:03:58

C#结构体变量

2009-09-04 17:34:11

C#CC++

2009-08-26 14:27:03

C# Framewor

2009-08-18 09:06:41

C#对象和集合

2009-08-03 15:06:43

C# Stack对象C# Queue对象

2009-08-11 13:13:09

C#和Java比较

2009-08-14 10:51:43

2009-09-17 17:13:54

C#数组

2009-08-10 10:04:25

C#抽象类C#接口

2009-08-21 10:28:21

C#异步方法C#同步方法

2009-08-11 10:12:21

2009-08-26 10:34:15

C#类型C#变量

2009-02-05 15:32:23

接口委托

2009-09-03 17:51:34

C#获取设备的ID

2009-06-24 10:25:25

C#泛型

2009-08-24 14:43:35

C# 泛型

2009-09-02 17:07:06

C#数组操作

2009-07-31 13:48:34

C# eval()函数

2009-08-20 18:30:33

C# ReaderWr

2011-09-21 10:56:31

C#结构
点赞
收藏

51CTO技术栈公众号