程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

C#指针的应用(c#指针操作)

balukai 2025-07-17 17:13:30 文章精选 4 ℃

C#在有限的范围内支持指针。C#的指针只不过是一个持有另一类型内存地址的变量。但是在C#中,指针只能被声明为持有值类型和数组的内存地址。与引用类型不同,指针类型不被默认的垃圾收集机制所跟踪。出于同样的原因,指针不允许指向引用类型,甚至不允许指向包含引用类型的结构类型。我们可以说,指针只能指向非托管类型,包括所有基本数据类型、枚举类型、其他指针类型和只包含非托管类型的结构。声明指针类型

声明指针类型的一般形式如下所示,

type *variable_name;

其中 * 称为取消引用运算符。例如下面的语句

int *x ;

声明一个指针变量x,它可以保存一个int类型的地址。引用操作符(&)可以用来获取一个变量的内存地址。

int x = 100;

&x 给出了变量 x 的内存地址,我们可以将它分配给一个指针变量

int* ptr = &x;.

Console.WriteLine((int)ptr) // Displays the memory address

Console.WriteLine(*ptr) // Displays the value at the memory address.

不安全代码

C#语句可以在安全或不安全的情况下执行。通过使用关键字unsafe标记为不安全的语句在垃圾收集器的控制之外运行。记住,在C#中,任何涉及指针的代码都需要一个不安全的上下文。我们可以通过两种不同的方式使用 unsafe 关键字。它可以用作方法、属性和构造函数等的修饰符。例如

// Author: rajeshvs@msn.com

using System;

class MyClass

{

public unsafe void Method()

{

int x = 10;

int y = 20;

int* ptr1 = &x;

int* ptr2 = &y;

Console.WriteLine((int)ptr1);

Console.WriteLine((int)ptr2);

Console.WriteLine(*ptr1);

Console.WriteLine(*ptr2);

}

}

class MyClient

{

public static void Main()

{

MyClass mc = new MyClass();

mc.Method();

}

}

关键字unsafe也可以用来标记一组语句为不安全,如下图所示。

// Author: rajeshvs@msn.com

//unsafe blocks

using System;

class MyClass

{

public void Method()

{

unsafe

{

int x = 10;

int y = 20;

int* ptr1 = &x;

int* ptr2 = &y;

Console.WriteLine((int)ptr1);

Console.WriteLine((int)ptr2);

Console.WriteLine(*ptr1);

Console.WriteLine(*ptr2);

}

}

}

class MyClient

{

public static void Main()

{

MyClass mc = new MyClass();

mc.Method();

}

}

固定住对象

在垃圾收集过程中,C#垃圾收集器可以随意移动内存中的对象。C#提供了一个特殊的关键字fixed来告诉垃圾收集器不要移动一个对象。这意味着这在内存中固定了值类型所指向的位置。这就是C#中所谓的固定住。


固定语句通常通过生成向垃圾收集器描述的表来实现,哪些对象将在可执行代码的哪些区域中保持固定。因此,只要在执行固定语句期间实际上没有发生垃圾收集器进程,与此相关的成本就非常低。但是,当垃圾收集器进程确实发生时,固定对象可能会导致堆碎片化。因此,只有在绝对必要时才应该Fixed对象,并且只能在最短的时间内Fixed。

指针和方法

这些点可以作为参数传递给一个方法,如下所示。这些方法也可以返回一个指针。

// Author: rajeshvs@msn.com

using System;

class MyClass

{

public unsafe void Method()

{

int x = 10;

int y = 20;

int* sum = swap(&x, &y);

Console.WriteLine(*sum);

}

public unsafe int* swap(int* x, int* y)

{

int sum;

sum = *x + *y;

return ∑

}

}

class MyClient

{

public static void Main()

{

MyClass mc = new MyClass();

mc.Method();

}

}

指针和转换

在C#中,指针类型不继承于对象,指针类型和对象之间不存在转换。这意味着指针不支持装箱和拆箱。但是C#支持不同的指针类型和指针类型与整型之间的转换。

C# 支持不安全上下文中的隐式和显式指针转换。隐式转换是

从任何类型的指针类型到 void * 类型。

从空类型到任何指针类型。

任何显式类型转换都需要强制转换运算符 (())。显式类型转换是

从任何指针类型到任何其他指针类型。

从 sbyte、byte、short、ushort、int、uint、long、ulong 到任何指针类型。

从任何指针类型到 sbyte、byte、short、ushort、int、uint、long、ulong 类型。

例如char c = 'R';

char* pc = &c;

void* pv = pc; // Implicit conversion

int* pi = (int*) pv; // Explicit conversion using casting operator

指针运算

在非安全的上下文中,++ 和 - 运算符可以应用于除 void * 类型之外的所有类型的指针变量。因此,对于每个指针类型 T*,以下运算符都被隐式重载。

T* operator ++ (T *x);

T* operator -- (T *x);

对于 T* 类型的指针变量,++ 运算符将 sizeof(T) 添加到变量中包含的地址,- 运算符从变量中包含的地址中减去 sizeof(–)。

在非安全的上下文中,可以从指针变量中添加或减去常量。类似地,可以从另一个指针变量中减去一个指针变量。但是在 C# 中不能添加两个指针变量。

在非安全的上下文中 ==, ! =、<、>、< =、> = 运算符可以应用于所有指针类型的值类型。指针变量与常量或另一个指针变量的乘法和除法在 C# 中是不可能的。

栈分配

在非安全的上下文中,局部声明可能包括栈分配初始化程序,它从调用栈分配内存。

stackalloc T[E] 要求 T 是非托管类型,E 是 int 类型的表达式。上面的构造从调用栈中分配 E * sizeof(T) 个字节,并生成一个指向新分配块的 T* 类型的指针。 E 为负,抛出 System.OverFlowException。如果没有足够的内存可供分配,则会引发
System.StackOverflowException。

新分配内存的内容未定义。无法隐式释放使用 stackalloc 分配的内存。相反,一旦函数返回,所有栈分配的内存块都会自动丢弃。

class Test

{

char *buffer =

}

指针和数组

在 C# 中,可以使用指针符号访问数组元素。

using System;

class MyClass

{

public unsafe void Method()

{

int[] iArray = new int[10];

for (int count = 0; count < 10; count++)

{

iArray[count] = count * count;

}

fixed (int* ptr = iArray)

Display(ptr);

//Console.WriteLine(*(ptr+2));

//Console.WriteLine((int)ptr);

}

public unsafe void Display(int* pt)

{

for (int i = 0; i < 14; i++)

{

Console.WriteLine(*(pt + i));

}

}

}

class MyClient

{

public static void Main()

{

MyClass mc = new MyClass();

mc.Method();

}

}

指针和结构

C# 中的结构是值类型。如果结构仅包含值类型作为其成员,则指针可以与结构一起使用。例如

using System;

struct MyStruct

{

public int x;

public int y;

public void SetXY(int i, int j)

{

x = i;

y = j;

}

public void ShowXY()

{

Console.WriteLine(x);

Console.WriteLine(y);

}

}

class MyClient

{

public unsafe static void Main()

{

MyStruct ms = new MyStruct();

MyStruct* ms1 = &ms;

ms1->SetXY(10, 20);

ms1->ShowXY();

}

}

Tags:

最近发表
标签列表