1. 程式人生 > 實用技巧 >C# 中的指標使用

C# 中的指標使用

C#中指標使用總結

C#為了型別安全,預設並不支援指標。但是也並不是說C#不支援指標,我們可以使用unsafe關鍵詞,開啟不安全程式碼(unsafe code)開發模式。在不安全模式下,我們可以直接操作記憶體,這樣就可以使用指標了。在不安全模式下,CLR並不檢測unsafe程式碼的安全,而是直接執行程式碼。unsafe程式碼的安全需要開發人員自行檢測。

一、Vs2010中開啟unsafe code 的方式

在方法、類、程式碼塊中使用unsafe關鍵詞,如:

unsafe static void Main(string[] args){ //程式碼}

unsafe
{
//程式碼塊
}


然後再專案上點選滑鼠右鍵,選擇“屬性”,在“生成”選項卡中選中“允許不安全程式碼”

二、C#可以定義為指標的型別有

sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool,
struct(結構體),結構體中只能包括非託管型別。

三、C#指標操作符

操作符 說明
* 取值運算子

& 取址運算子
-> 通過指標處理結構體中的資料(獲取或賦值)
++與– 指標增、減操作
fixed 使用者暫時固定託管程式碼中引用型別的位置。
Stackallc 分配記憶體

例如分配記憶體

char* cptr = stackalloc
char[26]; for (int i = 0; i < 26;i++ ) { cptr[i] = (char) (i+65); } for (int i = 0; i < 26;i++ ) { Console.WriteLine(string.Format("{0}:{1}",(int)&cptr[i],cptr[i])); }

至於釋放記憶體,我在msdn上搜索了一下,c#並沒有提供釋放記憶體的函式。而msdn給的解釋是:分配的記憶體會在方法結束後自動釋放。
fixed的應用會在下面的類與指標中做說明。

四、C#指標的定義

定義指標 說明
int* p 整形指標
int** p 指向整形指標的指標
char* c 指向字元的指標
int*[] arr 整形一維陣列指標

五、指標的使用

1.整形指標的使用

int i=10;
int* iptr = &i;    //將i的地址賦值給iptr
Console.WriteLine((int)&iptr);  //取iptr得地址
Console.WriteLine(*iptr);     //取iptr指向的值

2.結構體指標

struct Location
{
    public int X;
    public int Y;
}
unsafe static void Main(string[] args)
{
    Location location;
    location.X = 10;
    location.Y = 5;
    Location* lptr = &location;
    Console.WriteLine(string.Format("location 地址{0},lptr地址{1},lptr值{2}",(int)&location,(int)lptr,*lptr));
    Console.WriteLine(string.Format("location.x的地址{0},location.x的值{1}",(int)&(lptr->X),lptr->X));
    Console.WriteLine(string.Format("location.y的地址{0},location.y的值{1}", (int)&(lptr->Y), lptr->Y));
 }

以上程式碼輸出結構體的地址和值。我們在操作地址時,可以直接看到結構體的記憶體分配。

3.指標與引數

public static unsafe int* Add(int* x,int* y)
{
    int sum = *x + *y;
    return &sum;
}

int i = 2, j = 3;
Console.WriteLine(*Add(&i,&j));

4.類與指標,因為類是託管型別,我們知道類受到“垃圾收集”的影響,它的記憶體地址是不固定的。而且類是引用型別,是不能宣告為指標型別的。而指標分配記憶體後,不受“垃圾收集”影響,地址是固定的。所以為了使用類中的資料,我們需要臨時固定類的地址。這就用到fixed關鍵詞,用fixed後,就可以操作類中的值型別了。

class People
{
    public int Age;   //值型別,不可以是屬性
    public void ShowAge()
    {
        Console.WriteLine(Age);
    }
}


People people = new People();
people.Age = 10;
fixed(int* agePtr=&people.Age)
{
    *agePtr += 1;
}
people.ShowAge();  //11

通過以上的方法,我們可以操作值型別,也可以獲得值型別的地址。但如何獲取類的記憶體地址?我們可以使用GCHandle,來自System.Runtime.InteropServices名稱空間。GCHandle提供從非託管記憶體訪問託管物件的方法。如下:

object p = new People();
GCHandle h = GCHandle.Alloc(p, GCHandleType.Pinned);
IntPtr addr = h.AddrOfPinnedObject(); 
Console.WriteLine(addr.ToString());
h.Free();

六、C#中使用指標的總結

1.引用型別不能定義為指標
2.msdn上說enum可以定義為指標,可是我真不知道它的用處是什麼。所以在指標的型別中並沒有出現enum型別。
3.c#中的指標操作遠遠不如c/c++,如果想學習指標的話,還是用c/c++
4.微軟並不推薦使用unsafe code模式,也不推薦使用指標。在msdn官方文件中,唯一一句讚美C#指標的話就是“合理的使用指標,可以提高程式的執行速度”。但是什麼是“合理的使用”?我下載了msdn上的幾個關於C#指標的例項程式碼,發現用的最多的是呼叫api函式,在api函式中,有大量的指標引數。
5.fixed的使用可能產生儲存碎片,因為它們不能移動。如果確實需要固定物件,固定物件的時間應該越短越好。
6.可以使我們瞭解非託管型別的記憶體分配。

轉自https://www.cnblogs.com/nimorl/p/9829241.html