我想許多C程序員不願意學習Java的原因就是Java不支持指針,但是現在類似於Java的C#卻已經支持了指針,你可以使用unsafe關鍵字來告訴編譯器下面的函數或者代碼是不安全的。一旦你使用了unsafe,那麼你就可以在unsafe區域中使用指針。
程序1
using System;
class nish
{
unsafe static void Increment(int* p)
{
//increment the int pointed to by p
*p=*p+1;
}
public static void Main()
{
int i = 1;
//we pass the address of the int to the function as it expects a pointer
unsafe Increment(&i);
//now we print out the value of i
Console.WriteLine (i);
}
}
當你運行這個程序,你將會看到輸出結果2。這是因為你已經將變量i的地址送給了函數Increment來處理。變量i建立於棧中,&i則表示它在棧中的地址。這樣在函數Increment中,p就指向i的地址,當我們對*p加1時,實際上是對變量i進行增加。
程序2
下面的程序將會讓你更清楚的了解:
using System;
class nish
{
unsafe public static int Main()
{
int j=100;
int k=100;
Console.WriteLine("address of j={0} and address of k={1}",(int)&j,(int)&k);
Console.WriteLine("j={0} k={1}",j,k);
int *p;
p=&j;
Console.WriteLine("p now points to {0}",(int)p);
*p=200;
Console.WriteLine("j={0} k={1}",j,k);
p=&k;
Console.WriteLine("p now points to {0}",(int)p);
*p=300;
Console.WriteLine("j={0} k={1}",j,k);
return 0;
}
}
當運行上面的程序,我們將得到下面的結果。你會看到一些你熟悉的東東,下面的輸出結果將會清楚的看到程序執行的過程:
address of j=1244312 and address of k=1244308
j=100 k=100
p now points to 1244312
j=200 k=100
p now points to 1244308
j=200 k=300
首先將變量的j的地址賦給p,這樣當我們改變*p時,j的值也將自動改變。接著我們將p指向變量k的地址,這時改變*p則是在改變k。
同樣需要清楚的就是變量p也有自己的地址,下面的程序將會清楚的告訴您一切。
程序 3
using System;
class nish
{
public static void Main()
{
unsafe
{
int a=100;
int *p;
p=&a;
Console.WriteLine("address of a is {0}",(int)&a);
Console.WriteLine("p now points to {0}",(int)p);
Console.WriteLine("address of the pointer variable p is {0}",(int)&p);
}
}
}
一運行上面的代碼,我們將獲得下面顯示的輸出。你將同樣獲得一些類似的輸出,注意這裡unsafe關鍵字的使用。
address of a is 1244312
p now points to 1244312
address of the pointer variable p is 1244308
1244308是指針變量p的地址,而1244312則是指針p所指向的地址,我們使用*p來獲得。
程序 4
Okey。在最後的一個程序中,我將向大家介紹如何使用指針來操作字符串。在這個程序中存在一個程序來將一段字符串通過異或運算進行編碼解碼的操作。如果您將一段字符串送入這個函數這個字符串將會被編碼,如果您將一段已經編碼的字符送入這個函數,這段字符串將會被解碼。當這並不是一個安全的加密方法,我僅僅是想通過這個例子來演示一下指針的作用。
using System;
class nish
{
public static void Main()
[1] [2] 下一頁
{
string s="Code Project is cool";
Console.Write("the original string : ");
Console.WriteLine("{0}\r\n",s);
char[] b = new char[100];
s.CopyTo(0,b,0,20);
Console.Write("the encoded string : ");
unsafe fixed(char *p=b)NEncodeDecode(p);
for(int t=0;t<20;t++)
Console.Write(b[t]);
Console.WriteLine("\r\n");
Console.Write("the decoded string : ");
unsafe fixed(char *p=b)NEncodeDecode(p);
for(int t=0;t<20;t++)
Console.Write(b[t]);
Console.WriteLine();
}
unsafe public static void NEncodeDecode(char *s)
{
int w;
for(int y=0;y<20;y++)
{
w=(int)*(s+y);
w=w^5;
*(s+y)=(char)w;
}
}
下面是我得到的輸出,你也同樣可以得到:
the original string : Code Project is cool
the encoded string : Fja`%Uwjo`fq%lv%fjji
the decoded string : Code Project is cool
本例中,你會發現一個新的關鍵字--fixed。當你在語句或函數之前使用fixed時,你是在告訴.Net平台的垃圾回收器,在這個語句或函數執行完畢前,不得回收其所占的內存空間。fixed關鍵字只能在不安全的代碼中使用。本例中如果不使用fixed關鍵字,那麼這段程序的執行的結果是不可預知的,因為垃圾回收器會不斷的回收這些可控制代碼的所占用的內存空間。幸運的是,編譯器不會允許您指向可控制變量,除非您使用了fixed關鍵字。
在這個函數中,你看到我使用了*(s+y)表達式。s是指向字符串的地址(注意是首地址)。y則通過循環從0增加到19。這樣*(s)給我們的地址是1000,*(s+1)則是1002,*(s+2)則是1004,以此類推。編譯器知道我指向的是一個字符數據,因此第次就向前移動兩個字節,因為char是16位的(這與c是不同的,c中char只占8位)。
結論
使用不安全代碼時,必須十分小心,任何細小的錯誤,甚至是類型錯誤,都會導致輸出結果的不可遇知,而且這種錯誤是很難調試發現。當然如果您是C/C++程序員,您已經對指針了解得十分透徹,那麼當我的話沒有說。呵呵,祝好運。
上一頁 [1] [2]