using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//C#不安全代码
/*
* 当一个代码块使用unsafe修饰符标记时,C#允许在函数中使用指针变量。不安全代码或非托管代码是指使用了指针变量的代码块。
*
* 指针变量
* 指针是值为另一个变量的地址的变量,即,内存位置的直接地址。就像其他变量或常量,你必须在使用指针存储其他变量地址之前声明指针。
* type* var name;
*
* int* p p是指向整数的指针
* double* p p是指向双精度数的指针
* float* p p是指向浮点数的指针
* int** p p是指向整数的指针的指针
* int*[] p p是指向整数的指针的一维数组
* char* p p是指向字符的指针
* void* p p是指向未知类型的指针
*
* 在同一个声明中声明多个指针:
* int* p1,p2,p3;
*/
unsafe//或在Main方法上的void前添加unsafe关键字
{
int var = 20;
int* p = &var;
Console.WriteLine("Data is: {0}", var);
Console.WriteLine("Address is: {0}", (int)p);
}
//传递指针作为方法的参数
unsafe
{
TestPointer tp = new TestPointer();
int var1 = 10;
int var2 = 20;
int* x = &var1;
int* y = &var2;
Console.WriteLine("before: var1: {0}, var2: {1}", var1, var2);
tp.swap(x, y);
Console.WriteLine("after: var1: {0}, var2: {1}", var1, var2);
}
//使用指针访问数组元素
/*
* 在C#中,数组名称和一个指向与数组数据具有相同数据类型的指针是不同的变量类型。
* 例如,int *p和int[] p是不同的类型。你可以增加指针变量p,因为它在内存中是不固定的,但是数组地址在内存中是固定的,所以你不能增加数组p。
* 因此,如果你需要使用指针变量访问数组数据,可以像我们通常在C/C++中所做的那样,使用fixed关键字来固定指针。
*/
//实例
unsafe
{
int[] list = {10,100,200 };
fixed (int *ptr = list)
/*
* 在C#中声明的变量在内存中的存储受垃圾回收器的管理;因此一个变量(例如一个大数组)有可能在运行过程中被移动到内存中其他位置。如果一个变量的内存地址会变化,那么指针也就没有意义了。
* 解决方法是使用fixed关键字来固定变量位置不移动。
*
* 在unsafe不安全环境中,我们可以通过stackalloc在堆栈上分配内存,因为在堆栈上分配的内存不受内存管理器管理,因此其相应的指针不需要固定。
* static unsafe void Main(string[] args)
* {
* int *ptr = stackalloc int[1];
* }
*/
/*显示指针中数组地址*/
for(int i = 0;i<3;i++)
{
Console.WriteLine("Address of list[{0}] = {1}", i, (int)(ptr+i));
Console.WriteLine("Value of list[{0}] = {1}", i, *(ptr+i));
}
}
Console.ReadKey();
}
}
public class TestPointer
{
public unsafe void swap(int* p, int* q)
{
int temp = *p;
*p = *q;
*q = temp;
}
}
}