C++和C#的指针小解
????昨天和趙崇說了一下工作的事情,說起了性能問題就討論起了數(shù)據(jù)結(jié)果和指針對性能的影響。曾經(jīng)一直沒有想到這方面的事情,這幾天專門抽時(shí)間回想一下這方面的知識,然后一點(diǎn)一點(diǎn)的總結(jié)一下,看看數(shù)據(jù)結(jié)構(gòu)和指針在咱們代碼中是怎樣實(shí)現(xiàn)效率的提升的。
今天咱們先說一下指針。關(guān)于指針,在學(xué)C++的時(shí)候到時(shí)接觸過指針。可是當(dāng)時(shí)學(xué)的云里霧里,也沒能好好的總結(jié)一下,以至于忘的差點(diǎn)兒相同了,假設(shè)大家也有對指針不熟悉的地方。我們先來回想一下C++的指針吧。
?????? 在C++中。指針是這樣子定義的:指針是一個(gè)特殊的變量,它里面存儲的數(shù)值被解釋成為內(nèi)存里的一個(gè)地址。
要搞清一個(gè)指針須要搞清指針的四方面的內(nèi)容:指針的類型,指針?biāo)赶虻念愋?#xff0c;指針的值或者叫指針?biāo)赶虻膬?nèi)存區(qū)。還有指針本身所占領(lǐng)的內(nèi)存區(qū)。讓我們分別說明。
int *ptr; char *ptr; int **ptr; int (*ptr)[3]; int *(*ptr)[4];????? 通過上邊的樣例。大家把指針的申明語法去了。剩下的就是指針了。所以上邊的指針就是“ptr”。
然后我們看一下指針的類型:
int *ptr; //指針的類型是int * char *ptr; //指針的類型是char * int **ptr; //指針的類型是 int ** int (*ptr)[3]; //指針的類型是 int(*)[3] int *(*ptr)[4]; //指針的類型是 int *(*)[4]???? 怎么樣?找出指針的類型的方法是不是非常easy?
指針?biāo)赶虻念愋?/p>
????? 當(dāng)你通過指針來訪問指針?biāo)赶虻膬?nèi)存區(qū)時(shí),指針?biāo)赶虻念愋蜎Q定了編譯器將把那片內(nèi)存區(qū)里的內(nèi)容當(dāng)做什么來看待。
????? 指針?biāo)赶虻念愋?/p> int *ptr; //指針的類型是int char *ptr; //指針的類型是char int **ptr; //指針的類型是 int * int (*ptr)[3]; //指針的類型是 int()[3] int *(*ptr)[4]; //指針的類型是 int *()[4]
指針的值
???? 這個(gè)須要看操作系統(tǒng),假設(shè)咱們的系統(tǒng)是32位的。那么咱們的指針就是32位長度的一個(gè)值,由于計(jì)算機(jī)的內(nèi)存長度是32位。同理,64位的就是64位長度的值,當(dāng)然這個(gè)64和32。都是用0和1表示的,由于計(jì)算機(jī)僅僅能知道0和1.
???? 指針?biāo)赶虻膬?nèi)存區(qū)就是從指針的值所代表的那個(gè)內(nèi)存地址開始,長度為sizeof(指針?biāo)赶虻念愋?span style="font-family:Calibri;">)的一片內(nèi)存區(qū)。
以后,我們說一個(gè)指針的值是XX。就相當(dāng)于說該指針指向了以XX為首地址的一片內(nèi)存區(qū)域。我們說一個(gè)指針指向了某塊內(nèi)存區(qū)域。就相當(dāng)于說該指針的值是這塊內(nèi)存區(qū)域的首地址。
運(yùn)算符&和*
????? 這里&是取地址運(yùn)算符,*是...書上叫做“間接運(yùn)算符”。
&a的運(yùn)算結(jié)果是一個(gè)指針。指針的類型是a的類型加個(gè)*(比如int*)。指針?biāo)赶虻念愋褪?span style="font-family:Calibri;">a的類型(int)。指針?biāo)赶虻牡刂仿铩D蔷褪?span style="font-family:Calibri;">a的地址。
*p的運(yùn)算結(jié)果就五花八門了。
總之*p的結(jié)果是p所指向的東西。這個(gè)東西有這些特點(diǎn):它的類型是p指向的類型。它所占用的地址是p所指向的地址。
說過來翻過去。就是一個(gè)咱們手機(jī)導(dǎo)航過程。a就是你家,&a是指向你家的地址,比如p=&a,那么p就是我家的地址。那么*p的*就相當(dāng)于咱們手機(jī)的導(dǎo)航過。通過你輸入的地址,來找到你家。
?????? 上邊的樣例,僅僅是簡單的說了一下什么叫做地址。那么假設(shè)大家想要更深層次的理解指針的話。給大家推薦一篇博客,寫的很的基礎(chǔ)http://www.cnblogs.com/basilwang/archive/2010/09/20/1831493.html
????? 那么為什么要有指針呢,如不你設(shè)計(jì)一個(gè)函數(shù)
struct get(){
?.........
}
????? 返回一個(gè)結(jié)構(gòu)體對象的函數(shù),你要知道,C++中,這種返回值都是復(fù)制傳遞的過程。也就是說,你返回這個(gè)結(jié)構(gòu)體的時(shí)候,程序會復(fù)制一個(gè)一樣的結(jié)構(gòu)體對象在棧里面,然后接受的變量在通過拷貝構(gòu)造函數(shù),復(fù)制一個(gè)新的變量。
最后程序在析構(gòu)掉這個(gè)暫時(shí)的。
假設(shè)結(jié)構(gòu)體非常小。沒什么問題,假設(shè)非常大呢?這樣一構(gòu)造,一析構(gòu),會非常浪費(fèi)時(shí)間。可是指針就不一樣了,管你怎么弄,反正就是4字節(jié)。和一個(gè)int一樣,全然沒差別。
?????? 那么接下來咱們說一下C++到C#的”進(jìn)化史”吧,平時(shí)我們見的代碼好像沒有再像C++的代碼用到了指針,后來人們就說微軟是不是就沒有指針。事實(shí)上微軟是有的,大家右擊咱們的解決方式下的類庫-à生成à不安全代碼,大家勾選一下啊,一樣能夠用。僅僅只是寫類和方法的時(shí)候前邊加上個(gè)一個(gè)unsafe。比如:
??????
public partial unsafe class Demostatic unsafe void Copy(byte[] src, int srcIndex,byte[] dst, int dstIndex, int count){//。。。。。 }????? 另一個(gè)keyword要注意,那就是Fixed。他的作用就是一個(gè)釘子,大家看了上邊的介紹會發(fā)現(xiàn)指針事實(shí)上也是計(jì)算機(jī)中的0和1。
指針也占用內(nèi)存。僅僅是他的大小是固定的。
而fixed語句可用于設(shè)置指向托管變量的指針并在 statement 運(yùn)行期間“釘住”該變量。假設(shè)沒有 fixed語句。則指向可移動托管變量的指針的地址可變。由于垃圾回收可能不可預(yù)知地重定位變量。
????? C# 編譯器僅僅同意在 fixed語句中分配指向托管變量的指針,但無法改動在 fixed 語句中初始化的指針。
能夠用數(shù)組或字符串的地址初始化指針:
fixed (int* p = arr) ... // equivalent to p = &arr[0] fixed (char* p = str) ... // equivalent to p = &str[0]?????下邊為大家呈現(xiàn)一個(gè)完整的樣例,一個(gè)C#使用指針的樣例
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace cursorTest {class Program{// 使用unsafe標(biāo)注該方法static unsafe void Copy(byte[] src, int srcIndex,byte[] dst, int dstIndex, int count){if (src == null || srcIndex < 0 ||dst == null || dstIndex < 0 || count < 0){throw new ArgumentException();}int srcLen = src.Length;int dstLen = dst.Length;if (srcLen - srcIndex < count ||dstLen - dstIndex < count){throw new ArgumentException();}// 用fixed釘住指針。不讓他改變 fixed (byte* pSrc = src, pDst = dst){byte* ps = pSrc;byte* pd = pDst;// 循環(huán)復(fù)制for (int n = 0; n < count / 4; n++){*((int*)pd) = *((int*)ps);pd += 4;ps += 4;}//完畢賦值for (int n = 0; n < count % 4; n++){*pd = *ps;pd++;ps++;}}}static void Main(string[] args){byte[] a = new byte[100];byte[] b = new byte[100];for (int i = 0; i < 100; ++i)a[i] = (byte)i;Copy(a, 0, b, 0, 100);Console.WriteLine("The first 10 elements are:");for (int i = 0; i < 10; ++i)Console.Write(b[i] + " ");Console.WriteLine("\n");Console.ReadLine();}} }????? 可是為什么我們的代碼如今都不怎么用指針呢,由于在公共語言執(zhí)行庫 (CLR) 中,不安全代碼是指無法驗(yàn)證的代碼。C# 中的不安全代碼不一定是危急的,僅僅是其安全性無法由 CLR進(jìn)行驗(yàn)證的代碼。
因此。CLR 僅僅對在全然受信任的程序集中的不安全代碼運(yùn)行操作。假設(shè)使用不安全代碼。由您負(fù)責(zé)確保您的代碼不會引起安全風(fēng)險(xiǎn)或指針錯誤。所以你假設(shè)對你的代碼很有保證的話,用也是沒問題的。
總結(jié)
以上是生活随笔為你收集整理的C++和C#的指针小解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黑客惯用软件
- 下一篇: c# char unsigned_dll