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#...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- resize函数 (64)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- mybatis大于等于 (64)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- logstashinput (65)
- hadoop端口 (65)
- vue阻止冒泡 (67)
- oracle时间戳转换日期 (64)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)