本文基於flying_music部落格,加入自己的一些理解,請周知
1.印子——指標為什麼需要返回型別
我們用c語言寫了這樣的語句
[cpp]
view plain
copy
inta;
a = 3;
編譯器為了完成這兩句**,首先在編譯過程中要建立乙個符號表,樣子大概如下圖:
然後在執行過程中,編譯器發現a=3這句**時,會在符號表裡找a對應的位址,然後把3放入對應的位址,即這裡的0x1000。(a找b蓋章,直接蓋到了)
如果是*p=3會怎麼做呢?
首先,符號表變成了這個樣子
在執行過程中,編譯器遇到*p=3時,首先要從符號表中找到p的位址0x1004,然後
取出0x1004中的內容,這裡假設為0x2000,最後把3放到0x2000記憶體位址中,即*(0x1004)=3。
相比於利用普通變數,利用指標訪問資料的過程中多了一部取位址的的過程。這也就是指標變數與普通變數最大的不同。
再來看一下指標加偏移量的引用方式,還以上面的指標p為例,讓我們來看一下*(p+2)=3的實現過程。
首先,編譯器從符號表中找到p然後,取出裡面的內容0x2000,再根據其型別(int*),做乙個運算,
0x2000+2×sizeof(int)=0x2008。所以編譯器會把3放入0x2008這個記憶體位址。
整個過程可表示為*(*(0x1004)+2)=3。(a找b蓋章,b講你去c部門,找那誰蓋章(偏移))
從這裡也可以看出為什麼指標必須有型別,因為在引用過程中要用到指標所指型別的長度。
來看一下,陣列元素的引用是如何實現的,假設我們定義了乙個陣列,並對其元素進行了引用
[cpp]
view plain
copy
intb[10];
b[4] = 3;
對應的符號表變成了這個樣子
那b[4]=3如何完成呢?首先,找到符號b,然後發現其型別為int(假想表達方式,c語言中不支援這樣寫),所以計算式變成了0x1008+4×sizeof(int)=0x1018,然後把3放入0x1018就可以了。用乙個式子表達就是*(0x1008+4)=3。(a找b蓋章,b講你去我們部門,找那誰蓋章(偏移))
從上面的定址式子可以看出,普通變數、指標、陣列三者對於編譯器的區別。具體到陣列,它即具有普通變數的直接性,即不用取兩次位址裡的內容而是取一次,同時又具有和指標相同的偏移量引用方式,即下標的實現實際是由指標加偏移量實現的。
為了表明上述事實(或者是為了提高c語言入門門檻),c語言對指標與陣列的引用方式做了可以「交叉」使用的語法規定。就上面的例子來說,如果p指標指向陣列b時,b[i]、*(b+i)、p[i]、*(p+i)都是對陣列第i個元素的正確引用方式,這也給很多c語言學習者製造了「指標和陣列一樣」的錯覺。
2.在函式形參中的表現
在向函式傳遞引數時,如果實參是乙個一維陣列,那用於接受的形參為對應的指標。也就是傳遞過去是陣列的首位址而不是整個陣列。這麼做的原因主要是效率,這是無可爭議的,但為了使用上的簡便與通用,c語言接受兩種形參的寫法,即下面兩種寫法是相同的
[cpp]
view plain
copy
intfoo(
int*a,
intn);
intfoo(
inta,
intn);
甚至是[cpp]
view plain
copy
intfoo(
inta[20],
intn);
在底層都是完全一樣的形式。這簡化了c語言的使用,但同時也增加了對其進一步理解的難度。
至於哪種寫法好的爭論,只要理解了,用哪種寫法倒是不必強求。
指標形式表明了傳參過程的實質,而陣列形式表明了這個指標對應乙個陣列實參,甚至後面的數字可以提供陣列長度的參考。
3.如何區分二者
陣列和指標的關係如此微妙,那如何區分呢?
首先說為什麼要區分,主要由兩個方面的原因
一是c語言的主要戰場還是偏向於底層的,使用者對這塊兒一定要搞清楚,比如編譯器,硬體系統等相關知識。
二是在特定的情況下,二者的表現的確不同,最常見的就是sizeof關鍵字的作用結果,另外還有取址操作符&的結果等情況。
至於如何區分,個人認為凡是要區分兩個相關的概念,一定要將二者的作用區分清楚,即為什麼要有這個東西。
陣列和指標也是一樣,指標是一類特殊的變數,主要用途是函式間的傳址,用這種方式來改變實參內容。
而陣列是用來實現線性表的結構,用於把同類物件集中在一起放置。
所以,如果下次有人問你陣列和指標的區別,你首先第一句要說的就是二者根本沒有聯絡,這麼說並這麼理解,對於弄清這兩個傢伙的關係是很有裨益的。
指標知識點總結
用指標作函式引數。返回指標值的指標函式。指標陣列 指向指標的指標。main函式的命令列引數。指標與指標變數的概念 指標與位址運算子。變數 陣列 字串 函式 結構體的指標,以及指向變數 陣列 字串 函式 結構體的指標變數,通過指標引用以上各型別資料。指標與指標變數的概念。1 指標 就是記憶體中的乙個儲...
指標知識點總結
這周主要進行了與指標相關的內容的學習,以下是一些自己整理的關於指標的知識點總結,如果有缺差,歡迎指出。在不同的場合有不同的含義,我們要根據情況合理理解和使用 在定義變數的時候需要用 但是給指標變數賦值的時候不用 可以用來表示乙個變數是指標變數,值得注意的是,同一型別的指標變數只能指向同型別的變數的位...
陣列知識點總結
一 知識點總結 一維陣列 直接賦值 a 10 不賦初值 隨機值或0 全賦同一初值 a 10 或者更推薦用memset函式memset函式 memset 陣列名,值,sizeof 陣列名 如 memset a 0 sizeof a 二維陣列 int a 5 6 直接賦值 a 5 6 如果陣列大小較大 ...