百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

C#指针的应用(c#指针类型)

bigegpt 2025-06-13 11:31 8 浏览

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();

}

}

相关推荐

为3D手游打造, Visual Studio Unity扩展下载

IT之家(www.ithome.com):为3D手游打造,VisualStudioUnity扩展下载7月30日消息,微软正式发布升级版VisualStudioToolsforUnity扩...

由ArcMap属性字段自增引出字段计算器使用Python的技巧

1.前言前些日子有人问我ArcMap中要让某个字段的值实现自增有什么方法?我首先想到像SQLServer中对于数值型字段可以设置自增。所以我打开ArcCatalog查看发现只提供默认值,没办法只能看...

微软首次回答 HoloLens 相关问题,终于爆料了

fengo2015/04/2115:11注:本文作者张静是NVIDIAGPU架构师,微信公众号“黑客与画家”(HackerAndPainter),知乎专栏地址。欢迎各位童鞋与他交流探讨。...

C#指针的应用(c#指针类型)

C#在有限的范围内支持指针。C#的指针只不过是一个持有另一类型内存地址的变量。但是在C#中,指针只能被声明为持有值类型和数组的内存地址。与引用类型不同,指针类型不被默认的垃圾收集机制所跟踪。出于同...

C# 堆栈(Stack)(c# 堆栈中定位调用messagebox 的地方)

C#集合在C#中,堆栈(Stack)是一种后进先出(LIFO,LastInFirstOut)的数据结构。堆栈(Stack)适用于存储和按顺序处理数据,其中最新添加的元素会最先被移除。堆...

欢迎回来:Fortran意外重回流行编程语言20强榜单

TIOBE指数是用来确定一种编程语言受欢迎程度的指标之一。它并不表明哪种编程语言是最好的,也不表明哪种编程语言写的代码行数最多,而是利用在谷歌、维基百科、必应、亚马逊、YouTube等各种引擎和网站上...

C#+NET MAUI实现跨平台/终端(linux,win,ios等)解决方案

简介.NETMulti-platformAppUI(.NETMAUI)是一个跨平台的框架,用于使用C#和XAML创建移动和桌面应用程序。使用.NETMAUI,您可以用一套代码库开发可以在A...

C#代码安全红线:SQL注入防护终极方案,让你的系统固若金汤

在数字化时代,应用系统的安全性至关重要。而SQL注入攻击,长期盘踞在OWASP(OpenWebApplicationSecurityProject)漏洞榜单的前列,成为众多基于数据库的应用系统...

C# (一)状态机模式(状态机代码实现)

最近空闲,炒炒隔夜饭,以前这些模式在自己项目种应用过不少,但一直没有像别人那样写一个系列,最近年纪大了,很多东西都忘记了,特别AI的兴起,更少写代码了,反正没什么事情,自己在重写一遍吧。创建型模式(5...

C# 中 Predicate 详解(c#中的replace)

Predicate泛型委托:表示定义一组条件并确定指定对象是否符合这些条件的方法。此委托由Array和List类的几种方法使用,用于在集合中搜索元素。Predicate<T>...

C#中$的用法?(c#中&&什么意思)

文章来自AI问答。在C#中,$符号用于字符串插值(StringInterpolation)。字符串插值是C#6.0引入的一种特性,它允许你在字符串中直接嵌入表达式,而不需要使用string.For...

C#并行编程:Parallel类(c# 并行处理)

在Parallel类中提供了三个静态方法作为结构化并行的基本形式:Parallel.Invoke方法:并行执行一组委托。Parallel.For方法:执行与C#for循环等价的并行方法。Parall...

颠覆认知!用Span重构foreach循环竟让数据处理快如闪电

在C#编程的世界里,数据处理效率始终是开发者们关注的焦点。随着项目规模的扩大和数据量的激增,哪怕是细微的性能提升,都可能对整个应用的响应速度和用户体验产生深远影响。近年来,C#引入的Span<T...

Unity3D手游开发实践《腾讯桌球》客户端开发经验总结

本次分享总结,起源于腾讯桌球项目,但是不仅仅限于项目本身。虽然基于Unity3D,很多东西同样适用于Cocos。本文从以下10大点进行阐述:1.架构设计2.原生插件/平台交互3.版本与补丁4.用脚本,...

.NET 7 AOT 的使用以及 .NET 与 Go 互相调用

目录背景C#部分环境要求创建一个控制台项目体验AOT编译C#调用库函数减少体积C#导出函数C#调用C#生成的AOTGolang部分安装GCCGolang导出函数.NETC#...