C#变量类型(1):指针

原创 2003年12月11日 11:41:00
 

    本课将简单介绍指针以及它在C#中的使用,不过本课程仅仅会涉及到一些指针方面的浅显知识,如果你对指针不是十分的熟悉,而你又偏偏希望在你的代码中使用指针,我们建议你更深入的了解它。幸运的是,在C#中只有当程序运行速度是极其重要的时候才需要使用到指针。(大多数情况下,我们可以不去理会指针。)

       指针符号

       指针是一个保存其他类型数据存储地址的变量。在C#中,指针只能指向值类型数据以及数组。

       指针以如下的方式使用*隐式定义:

       int *p;

       有些程序员可能会把*直接放在类型名的后面,例如:int* p,这种定义指针的方式和前一种方式工作情况完全相同。

       上面的定义将创建一个指针pp将保存一个整数(占用4字节)的初始内存地址。

       *p(在p前加上*前缀)这种复合语法元素可以用来代表由p指向的内存中存放的实际数据。因此如果给出声明后,*p能够出现在赋值号的左边,如下所示:

*p5

这行代码将5赋值给由上面的声明语句初始化的整数。不过,对于如下的赋值语句你可能会感到迷惑:

p5

这条语句的效果是改变p保存的内存地址,它并不会改变由初始化声明语句初始化的整数值。这仅仅意味着p将不再指向这个整数。事实上,p现在将指向由内存地址5开始的连续的4个字节(int类型占用的内存位数)。

使用指针的另一个重要的符号是地址运算符&,它会返回变量存储的内存地址。下面是使用这个符号的一个例子,这个例子创建了一个指向整型变量i的指针p

int i = 5;
int *p;
p = &i;

在上面的代码的基础上,代码

*p10

将改变变量i的值为10。因为*p能被理解为保存在由p指向的内存中的整数。

对于指向结构类型的指针还有另外一个重要的符号->。我们可以声明一个指向结构类型的指针,如下所示:(下面的例子中使用到了’Coords’结构,后面的代码中还会使用到)

Coords x = new Coords();
Coords *y = &x;

然后我们可以使用定义的指针y访问x的一个公共成员(例如z)。我么可以使用如下的两种方式:

(*y).z

y -> x//使用到符号->

不安全代码

C#中使用指针的一个主要问题是C#管理环境垃圾收集。在清理内存空间时,垃圾收集器可能在不加警告的情况下改变一个现存类型的存储位置。这时以前指向这个类型的指针将不能再指向它了。这样一种情况将会导致两种潜在的问题。其一,它可能危及到这个C#程序的运行;其二,它可能影响到其他程序的完整性。

正因为上述问题,C#限制指针只能使用在由程序员明确声明为’unsafe’的代码中。因为不安全代码潜在的恶意使用问题,包含不安全代码的程序仅仅当他们能被完全信任时才能运行。

针对垃圾收集器移动数据存储位置的问题,你可以使用’fixed’表达式声明一个指针。这将固定指针指向的数据的位置,这样这个数据的存储位置将保持固定不变,不受垃圾收集器的影响。不过,’fixed’语句只能使用在不安全代码中。

另外值得注意的是,任何在不安全代码中声明的值类型自动变为’fixed’,而且如果你对他们使用了’fixed’表达式,将会产生运行时错误。不过,这条规则并不适用于引用类型(数组)。

下面的代码给出了一个标记为’unsafe’的方法的例子,从前面的讲述中,我们知道第9行的指针p不能使用’fixed’语句声明,因为p指向的是一个已经在不安全代码中声明的结构类型c

1.

using System;

2.

public struct Coords

3.

{

4.

    int x;

5.

    int y;

6.

    unsafe public static void Main()

7.

    {

8.

        Coords c = new Coords();

9.

        Coords *p = &c;

10.

        {

11.

            p->y = 6;

12.

            (*p).x = 5;

13.

        }

14.

        Console.WriteLine(c.y);

15.

        Console.WriteLine(c.x);

16.

    }

17.

}

我们再看看下面的代码,在第8行的指针p必须使用’fixed’语句声明,因为它指向了一个不是在不安全代码段中声明的类型。

1.

using System;

2.

public struct Coords

3.

{

4.

    int x;

5.

    int y;

6.

    unsafe public static void notMain(ref Coords c)

7.

    {

8.

        fixed (Coords *p = &c)

9.

        {

10.

            p->y = 6;

11.

            (*p).x = 5;

12.

        }

13.

        Console.WriteLine(c.y);

14.

        Console.WriteLine(c.x);

15.

    }

16.

}

在上面给出的例子中,’unsafe’都是作为方法的修饰符,不过你也可以在一个代码段中使用它,下面的例子显示了这种用法:

1.

using System;

2.

public static void Main()

3.

{

4.

    unsafe

5.

    {

6.

        Coords c = new Coords();

7.

        [...]

8.

    }

9.

}

指针、方法和数组

虽然在上面的讲述中我们使用的指针都是指向一个值类型,但是指针也可以指向数组(引用类型)。(也有一些作者认为指针也可以指向字符串)

指针可以像下面的示例那样声明为指向一个数组:

int[] a = {4, 5};
int *b = a;

在这种情况下,b保存的内存地址是数组a的第一个元素的位置。正如前所述,这个元素必须是一个值类型。下面的代码显示了如何使用一个指针改变数组的各个元素的值,对此的解释不在本文讨论范围之列。

1.

using System;

2.

public class Tester

3.

{

4.

    public static void Main()

5.

    {

6.

        int[] a = {4, 5};

7.

        changeVal(a);

8.

        Console.WriteLine(a[0]);

9.

        Console.WriteLine(a[1]);

10.

    }

11.

    

12.

    public unsafe static void changeVal(int[] a)

13.

    {

14.

        fixed (int *b = a)

15.

        {

16.

            *b = 5;

17.

            *(b + 1) = 7;

18.

        }

19.

    }

20.

}

 

 

 

在c#中使用指针

如果想在c#中使用指针,首先对项目进行配置:在解决方案资源管理器中右击项目名选择属性(或在项目菜单中选择consoleApplication属性(consoleApplication为项名)),在生成...
  • susan19890313
  • susan19890313
  • 2012年03月19日 10:33
  • 16525

C# 指针之美

将C#图像库的基础部分开源了(https://github.com/xiaotie/GebImage)。这个库比较简单,且离成熟还有一段距离,但它是一种新的开发模式的探索:以指针和非托管内存为主的C#...
  • huyu107
  • huyu107
  • 2016年07月26日 14:38
  • 196

C#下的指针运用

    使用指针,就可以访问实际内存地址,执行新类型的操作。例如,给地址加上4字节,就可以查看甚至修改存储在新地址中的数据。下面是使用指针的两个主要原因: 向后兼容性。      尽管.NET 运行库...
  • a237428367
  • a237428367
  • 2010年10月07日 15:44
  • 9913

C++中指针与C#中引用类型传递相似性

C++中指针与C#中引用类型非常相似,不仅体现在可以在任意传递函数中修改其指向的值,更体现在传递时,修改其指向: 改变指针指向的内存空间、改变引用类型变量指向的引用。通过以下的例子可清晰对比两者间的相...
  • yanfk
  • yanfk
  • 2016年12月14日 22:59
  • 498

C#指针类型

操作c#中的指针,是一种编写非托管中的一种技术。c#中指针类型可能是(存储在栈)中的值类型,也可能是(存储在堆)中的引用类型。不过无论是什么类型,基本格式都有一个共同的要求就是必须都是支持非托管的类型...
  • C_Link
  • C_Link
  • 2011年02月27日 22:39
  • 570

C# 指针学习笔记之指针类型

大学的时候学过C++、C,最近工作也不是很忙,就想起看看C#中的指针,看看、回忆一下啊,指针的用法,一下学习笔记摘自msdn:指针类型 在不安全的上下文中,类型可以是指针类型以及值类型或引用类型。...
  • xunzaosiyecao
  • xunzaosiyecao
  • 2014年09月05日 09:31
  • 2209

c#调用Win32 API如何处理指针类型的参数

0、前言 从VB到C#,被人诟病比较多的就是交互性比较差,又集中表现在调用Win32 API上。如果说C/C++调用API只是调用函数这类轻松的活,在C#下却成了阻挡入门者的技术活。之所以产生这么大区...
  • iamherego
  • iamherego
  • 2016年01月06日 15:35
  • 707

C#中取得变量的指针的方法

int lPort; unsafe {     // Assign the address of number to a pointer:      // int* p= &lPort;  ...
  • wletv
  • wletv
  • 2011年10月14日 20:17
  • 3536

C#中对象指针的使用

1,得到某个类的实例的指针。MyClass newClass = new MyClass();RuntimeTypeHandle handle = newClass.GetType().TypeHan...
  • zfrong
  • zfrong
  • 2009年07月16日 12:56
  • 3835

C#中的变量类型

C#中的变量类型分为两种:值类型和引用类型。 其中值类型比较好理解:概念上,值类型变量是直接存储其值,存储在堆栈中;   举例说明: int是值类型,表示下面的语句会在内存的两个地方存数值20:   ...
  • liangqichan
  • liangqichan
  • 2015年09月09日 15:16
  • 1125
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#变量类型(1):指针
举报原因:
原因补充:

(最多只允许输入30个字)