1. 程式人生 > 實用技巧 >C語言中的指標筆記

C語言中的指標筆記

1.為什麼需要指標:

  • 指標的使用使得不同區域的程式碼可以輕易的共享記憶體資料。當然你也可以通過資料的複製達到相同的效果,但是這樣往往效率不太好,因為諸如結構體等大型資料,佔用的位元組數多,複製很消耗效能。但使用指標就可以很好的避免這個問題,因為任何型別的指標佔用的位元組數都是一樣的(根據平臺不同,有4位元組或者8位元組或者其他可能)。
  • 指標使得一些複雜的連結性的資料結構的構建成為可能,比如連結串列,鏈式二叉樹等等。
  • 有些操作必須使用指標。如操作申請的堆記憶體。
  • C語言中的一切函式呼叫中,實參傳遞給形參的機理都是“按值傳遞(pass by value)”,如果我們要在函式中修改被傳遞過來的物件,就必須通過這個物件的指標來完成。

2.什麼是指標:指標是程式資料在記憶體中的地址,而指標變數是用來儲存這些地址的變數。C語言中的陣列是指 一類 型別,陣列具體區分為 int 型別陣列,double型別陣列,char陣列 等等。同樣指標 這個概念也泛指 一類 資料型別,int指標型別,double指標型別,char指標型別等等。

3.為什麼程式中的資料會有自己的地址:作業系統將DRAM等硬體和軟體結合起來,給程式設計師提供的一種對實體記憶體使用的抽象。這種抽象機制使得程式使用的是虛擬儲存器,而不是直接操作物理儲存器。所有的虛擬地址形成的集合就是虛擬地址空間。 由於記憶體中的每一個位元組都有一個唯一的編號,因此,在程式中使用的變數,常量,甚至數函式等資料,當他們被載入到記憶體中後,都有自己唯一的一個編號,這個編號就是這個資料的地址。

指標就是這樣形成的。

4.空指標:指向空,或者說不指向任何東西。在C語言中,我們讓指標變數賦值為NULL表示一個空指標,而C語言中,NULL實質是 ((void*)0) , 在C++中,NULL實質是0。換種說法:任何程式資料都不會儲存在地址為0的記憶體塊中,它是被作業系統預留的記憶體塊。

5.壞指標:指標變數的值是NULL,或者未知的地址值,或者是當前應用程式不可訪問的地址值,這樣的指標就是壞指標,不能對他們做解指標操作,否則程式會出現執行時錯誤,導致程式意外終止。任何一個指標變數在做 解地址操作前,都必須保證它指向的是有效的,可用的記憶體塊,否則就會出錯。壞指標是造成C語言Bug的最頻繁的原因之一。

6.void*型別指標:由於void是空型別,因此void*型別的指標只儲存了指標的值,而丟失了型別資訊,我們不知道他指向的資料是什麼型別的,只知道這個資料在記憶體中的起始地址,如果想要完整的提取指向的資料,程式設計師就必須對這個指標做出正確的型別轉換,然後再解指標。前面已經提到過,資料的型別是正確解析出記憶體資料的關鍵,相同的記憶體資料以不同的資料型別去解析的時候,會得到不同的值。程式需要得到什麼資料,不光要知道其地址,還要明確其型別,因此編譯器不允許直接對void*型別的指標做解指標操作

7.&是返回運算元地址的單目運算子,叫做取地址運算子。*是返回指定地址內變數的值的單目運算子,叫做指標運算子。

8.字元陣列和字元指標:字元指標可以指向一個字串。字元指標指向的是一個字串常量的首地址,即指向字串的首地址。以字串形式出現的,編譯器都會為該字串自動新增一個0作為結束符,如在程式碼中寫:"abc",那麼編譯器幫你儲存的是"abc/0"。字元指標str與字元陣列string的區別是:str是一個變數,可以改變str使它指向不同的字串,但不能改變str所指的字串常量。string是一個數組,可以改變陣列中儲存的內容。

9.const char*是指向常量的指標,而不是指標本身為常量,可以不被初始化.該指標可以指向常量也可以指向變數,只是從該指標的角度而言,它所指向的是常量,通過該指標不能修改它所指向的資料。

10.指標完全可以作為函式的引數進行傳遞,在C中,陣列作為引數傳遞,跟指標作為引數傳遞都很類似的,指標傳的是該指標指向的地址,而陣列引數則是將該陣列的首地址傳遞過去

11.檔案指標:在C語言中用一個指標變數指向一個檔案,這個指標稱為檔案指標。通過檔案指標就可對它所指的檔案進行各種操作。

12.指標常量,常量指標

什麼是指標常量?指標常量即指標型別的常量。

char *const name1="John";
name1="abc";         //錯誤,name1指標,不能變,一個指標型別的變數,存放的是地址,所以不能把'"abc"的地址賦給name1
char * name2= name1; //可以

什麼是常量指標?常量指標即是指向常量的指標,指標的值可以改變,指標所指的地址中的內容為常量不能改變。

const char *name1="John";
char s[]="abc"; name1=s;   //正確,name1存放的地址可以改變
char * name2= name1;       //不可以,因為name2 和 name1存放的是同一塊地址,如果name2地址中的內容改了,則name1的內容也改了,那麼name1就不再是指向常量的指標了。