第一篇:學(xué)習(xí)指針萬用表要求掌握的技能(最終版)
學(xué)習(xí)指針萬用表要求掌握的技能
1、掌握萬用表使用原則
2、知道一些指針萬用表和數(shù)字萬用表的區(qū)別
3、掌握指針式萬用表的測量計算原理
4、熟練掌握單手操作
5、會保護(hù)維修萬用表的表筆
6、萬用損壞后,能根據(jù)先前操作和現(xiàn)象,判斷萬用表損壞原因,7、區(qū)分在什么情況下進(jìn)行歐姆調(diào)零和機械調(diào)零,并掌握其用法
8、會選擇合適的檔位測量電阻,會歐姆調(diào)零,會讀數(shù),會計算。
9、熟練掌握在不同檔位(1000v、500v、250v)測量插座電壓,會讀數(shù),會計算
10、熟練判斷零線和火線,掌握握筆方法,知道其安全原理
11、熟練測量直流電壓和直流電流,知道直流和交流的不同之處,知道測量電壓和電流的不同之處,且要會讀數(shù),會計算
12、會使用萬用表的標(biāo)準(zhǔn)電阻箱
13、知道9v電池和1.5v電池對萬用表測量的影響,知道10k檔位的作用。
14、知道交流電壓檔10v檔位使用的是獨立的刻度線
15、知道如何測量三極管的放大倍數(shù)
16、知道如何測量1000v以上的交流電壓和直流電壓,并會選擇檔位,會選擇插孔,會計算。
17、知道如何測量500mA以上的直流電流,并會選擇檔位,會選擇插孔,會計算。
18、會測量電池電量是否充足,并會選擇檔位,會看表盤。
19、知道表盤上標(biāo)號的意思
第二篇:磁電式指針萬用表原理與維修總結(jié)
磁電式指針萬用表維修總結(jié)
MF-47型指針萬用表原理與維修經(jīng)驗總結(jié)
指針系儀表分為磁電式和電磁式兩種,現(xiàn)在的指針萬用表都是以磁電式儀表為主,由于電磁式儀表靈敏度較低,所以電磁式儀表一般應(yīng)用在工業(yè)用電的電壓表和電流表中,磁電式儀表根據(jù)磁路不同分為,內(nèi)磁,外磁,內(nèi)外磁,三種,其中外磁表頭的指針萬用表很容易受到外磁場的干擾而引起測量不準(zhǔn)現(xiàn)象,所以外磁表頭的指針萬用表一般會在萬用表后蓋板上設(shè)計一塊金屬屏蔽板,金屬屏蔽板的作用就是屏蔽外界電磁場干擾讓表頭測量的更佳精準(zhǔn),因為外磁表頭很容易引入外界電磁場干擾,而引起測量不準(zhǔn)現(xiàn)象,所以通過在萬用表后蓋板上加裝金屬屏蔽板來進(jìn)行外磁屏蔽,從而讓外磁表頭測量的更佳精準(zhǔn),而內(nèi)磁表頭一般是不會設(shè)計的,因為內(nèi)磁表頭不易引入外磁場干擾,內(nèi)磁表頭抗干擾能力強。
下面介紹下磁電式儀表的內(nèi)部構(gòu)成:
磁電式儀表內(nèi)部有兩部分組成一部分是可動部分一部分是固定部分,固定部分:磁鋼,可動部分:彈簧游絲,指針,阻尼器,這兩部分組成,其中磁鋼的作用主要是通入電流產(chǎn)生磁場力,彈簧游絲的作用主要是產(chǎn)生反作用力矩帶動表針偏轉(zhuǎn),阻尼器的作用是,當(dāng)指針受到磁場力的作用而偏轉(zhuǎn)時會產(chǎn)生一定的慣性而阻尼器的作用就是吸收這部分慣性讓指針可以盡快的停止在某一點上以達(dá)到快速讀數(shù)的目的。
下面講解一下:磁電式儀表的工作原理:
現(xiàn)在所有機械式萬用表(即指針萬用表)都是磁電式儀表,磁電式儀表根據(jù)磁路不同,分為內(nèi)磁,外磁,內(nèi)外磁三種,其工作原理是:當(dāng)電流通入表頭內(nèi)部的磁鋼時,電流切割磁感線,會產(chǎn)生一個磁場力也就是我們所謂的(轉(zhuǎn)動力矩),這個磁場力(轉(zhuǎn)動力矩)會帶動表頭內(nèi)部的彈簧游絲,彈簧游絲會帶動指針偏轉(zhuǎn),根據(jù)通入表頭內(nèi)部磁鋼電流大小不同,產(chǎn)生的磁場力強弱也不同,從而游絲帶動指針偏轉(zhuǎn)的幅度也不同,也就是說,通入磁鋼電流越大,產(chǎn)生的磁場力越強,所以彈簧游絲帶動指針偏轉(zhuǎn)的幅度也就越大說明被測信號很大,反之,通入磁鋼電流越小產(chǎn)生的磁場力越弱,所以游絲帶動指針偏轉(zhuǎn)的幅度也就越小說明被測信號很小,通過這個原理實現(xiàn)測量信號的大小。而彈簧游絲的作用主要是產(chǎn)生反作用力矩的裝置,我們知道指針偏轉(zhuǎn)是受到磁場力(轉(zhuǎn)動力矩)的作用而偏轉(zhuǎn),而游絲主要是產(chǎn)生一個反作用力矩,簡單的來講,游絲主要是產(chǎn)生一個與磁場力相反的力矩,我們稱它為反作用力矩,當(dāng)磁場力(轉(zhuǎn)動力矩)與游絲產(chǎn)生的反作用力矩相等時指針停止,磁場力(轉(zhuǎn)動力矩)帶動指針向右偏轉(zhuǎn),游絲自身產(chǎn)生一個反作用力矩向左拉抻指針,當(dāng)磁場力(轉(zhuǎn)動力矩)與游絲產(chǎn)生的反作用力矩相等時,指針停止從而讀數(shù)。如果只有磁場力(轉(zhuǎn)動力矩)沒有游絲產(chǎn)生的反作用力矩的話不管測量的信號有多大指針都會偏轉(zhuǎn)到頭。
下面以國產(chǎn)MF-47為例講解指針表原理與維修:
MF-47型指針表的表頭是一個微安(μA)級的直流電流表,它的滿偏轉(zhuǎn)度為46.2微安,也就是說表頭滿篇電流為46.2微安,其工作原理:當(dāng)有電流信號流過表頭,表針會受到磁場力的作用而偏轉(zhuǎn),(因為有電流的地方就會產(chǎn)生磁場)根據(jù)磁場力大小不同,表針偏轉(zhuǎn)的幅度也不同,也就是說,流過表頭電流越大產(chǎn)生的磁場力越強,所以游絲帶動表針偏轉(zhuǎn)的幅度也就越大,流過表頭電流越小,產(chǎn)生的磁場力越弱所以游絲帶動表針偏轉(zhuǎn)的幅度也就越小,它們成正比關(guān)系。即電流越大磁場力越強,游絲帶動指針偏轉(zhuǎn)幅度也就越大,電流越小,磁場力越弱,游絲帶動指針偏轉(zhuǎn)的幅度也就越小。
指針萬用表調(diào)零方法與調(diào)零原理:
機械調(diào)零:指針沒有指向0位使用螺絲刀擰動機械調(diào)零旋鈕將指針歸0,機械調(diào)零原理:機械調(diào)零旋鈕內(nèi)部接著一個機械調(diào)零螺絲,通過擰動機械調(diào)零旋鈕相當(dāng)于擰動機械調(diào)零螺絲,從而將指針歸0 歐姆調(diào)零:將萬用表打到電阻擋,因為在萬用表里只有電阻擋才用內(nèi)部電池工作,短接表筆相當(dāng)于短接內(nèi)部電池有電流流過表頭,表針偏轉(zhuǎn),表針沒有指向0位,擰動電阻調(diào)零電位器將指針歸0,歐姆調(diào)零原理:電阻調(diào)零電位器控制一個可調(diào)電阻,通過擰動電阻調(diào)零電位器相當(dāng)于改變可調(diào)電阻的電阻值從而改變流過表頭電流大小來進(jìn)行調(diào)零。
測量原理: DC:直流 AC:交流
DCV直流電壓擋測量原理:通過與表頭串聯(lián)電阻分壓來擴大電壓擋測量量程,因為測量的是直流信號,所以不用走半波直接可以走表頭來測量,通過改變直流電壓擋中串聯(lián)分壓電阻的阻值就可以改變測量量程的范圍,每個檔位的分壓電阻都要與保險管相連接。
DCmA直流電流擋測量原理:通過與表頭并聯(lián)電阻分流來擴大電流擋測量量程,改變直流電流擋中并聯(lián)分流電阻的阻值就可以改變測量量程的范圍,每個檔位的分流電阻都要與保險管相連接。
ACV交流電壓擋測量原理:通過與表頭串聯(lián)電阻分壓來擴大交流電壓擋測量量程,在走半波整流電路將交流信號整流變?yōu)橹绷餍盘柫鬟^表頭來測量,因為指針表的表頭是一個直流電流表,表頭無法流過交流信號所以必須要在交流電壓擋中加上一個半波整流電路做整流器將被測量的交流信號整流變?yōu)橹绷餍盘柫鬟^表頭來測量,所以說測量一次交流電就要經(jīng)過整流二極管整流一次,交流電壓擋必須走整流器要將被測量的交流信號整流變?yōu)橹绷餍盘柫鬟^表頭來測量。交流電壓擋相當(dāng)于是在直流電壓擋的電阻串聯(lián)分壓來擴大電壓擋量程基礎(chǔ)上加裝了一個整流器,構(gòu)成了交流電壓擋。
當(dāng)交流電正半周時經(jīng)過D1整流將交流信號整流變?yōu)橹绷餍盘柫鬟^表頭來測量,交流電負(fù)半周時經(jīng)過D2整流,這里的D2是為了保護(hù)D1整流二極管,為了防止 交流電正負(fù)半周時都經(jīng)D1整流,由于交流電壓信號過大很容易將D1擊穿,所以加了一個D2整流二極管,這樣的話正半周時經(jīng)過D1整流將交流信號變?yōu)橹绷餍盘柫鬟^表頭來測量,負(fù)半周時經(jīng)過D2整流將交流信號整流變?yōu)橹绷餍盘柫鬟^表頭來測量。
Ω電阻擋測量原理:電阻擋是在萬用表里唯一使用電池工作的檔位,MF-47指針表內(nèi)部有兩塊電池一塊1.5V一塊9V,電阻擋共分為五個量程,其中RX10K獨立使用內(nèi)部9V電池供電 RX1K RX100 RX10 RX1四個檔位共用內(nèi)部1.5V,如果被測電阻阻值很大,則流過被測電阻的電流就很小,這時候表針偏轉(zhuǎn)的幅度就很小說明被測電阻阻值很大,反之如果被測電阻阻值很小,則流過被測電阻的電流就很大,這時候表針偏轉(zhuǎn)的幅度也就很大,說明被測電阻的阻值很小,通過這個原理實現(xiàn)測量電阻的大小。
MF-47萬用表保護(hù)電路講解:
1:表頭保護(hù):表頭鉗位保護(hù),利用兩只IN4001硅整流二極管并聯(lián)構(gòu)成雙向限幅二極管接入表頭目的是防止勿用電流擋去測量電壓而燒表頭這樣的話輸入電壓信號會被雙向限幅二極管牽制在0.7V即硅二極管導(dǎo)通電壓,從而來保護(hù)表頭。
表頭跨接電容C1作用是給表頭濾波,防止流過表頭的直流信號有雜波影響測量誤差,R1是限流保護(hù)電阻,防止流過表頭電流過大而燒表頭。
2:所有檔位使用閉路式分流器:直流電壓擋。交流電壓擋,直流電流擋所有分壓電阻和分流電阻都是串聯(lián)起來的這樣的話一只分壓電阻或分流電阻損壞該檔位所有量程都是無法使用的。
3:輸入保險管:FUSE 250V/0.5A輸入電流值大于(AC/DC)0.5A該保險管會自動熔斷,以達(dá)到保護(hù)后級電路目的。
新型天宇MF-47,電阻擋設(shè)計一個壓敏電阻,做過壓保護(hù)元件,為了防止用電阻擋去測量220V交流電壓而燒電阻擋電阻,以及其它元件,所以在電阻中設(shè)計一個壓敏電阻,即使使用萬用表電阻擋去測量220V電壓也不比害怕燒表。
指針萬用表故障維修講解:
指針萬用表表頭故障講解:現(xiàn)在的所有指針萬用表都是磁電式表頭,磁電式表頭構(gòu)成:磁鋼,動圈,阻尼器,彈簧游絲,以及指針幾部分組成,其中磁鋼的作用是通入電流產(chǎn)生磁場力,彈簧游絲的作用主要是產(chǎn)生反作用力矩帶動指針偏轉(zhuǎn),阻尼器的作用是當(dāng)指針受到磁場力的作用而偏轉(zhuǎn)時會產(chǎn)生一定慣性而阻尼器的作用就是吸收這部分慣性讓指針可以盡快的停止在某一點上以達(dá)到快速讀數(shù)的目的。
表頭故障維修:表頭維修講解: 故障1:指針無法偏轉(zhuǎn),首先要檢查萬用表保險管,防止內(nèi)部輸入保險管被燒斷引起沒有電流輸入,從而導(dǎo)致表針無法偏轉(zhuǎn),第二步,如果保險管正常,則要試試所有檔位,即直流電壓擋,交流電壓擋,直流電流擋,看看所有檔位測量的時候指針是否都無法偏轉(zhuǎn),如果所有檔位在測量時指針都無法偏轉(zhuǎn)則說明故障在表頭,因為保險管是好的,但是所有檔位都無法用,這么說的話,萬用表內(nèi)部直流電壓擋串聯(lián)分壓電阻,和交流電壓擋串聯(lián)分壓電阻和整流器,以及電流擋的分流電阻不可能全部損壞,所以說,指針不動的原因就是由于表頭有問題引起的,檢查方法如下,可以通過測量表頭滿篇電流,當(dāng)然如果覺得麻煩的話可以采取更換一個同樣大小的表頭。
表頭維修講解: 故障2:指針偏轉(zhuǎn)幅度較大,如果測試中發(fā)現(xiàn),所有檔位測量信號的時候,指針偏轉(zhuǎn)幅度都很大,超過測量中的實際值,排除,保險管有問題,在排除內(nèi)部分壓分流電阻有短路或開路現(xiàn)象,則要檢查表頭,檢查:表頭內(nèi)部的平衡錘,彈簧游絲,彈簧游絲是重點檢查的對象,因為我們知道游絲的作用是產(chǎn)生反作用力矩帶動指針偏轉(zhuǎn),而讓指針偏轉(zhuǎn)的是磁場力,磁場(轉(zhuǎn)動力矩),光有磁場力(轉(zhuǎn)動力矩)沒有游絲產(chǎn)生的反作用力矩的話,不管測量的信號有多大指針都會偏轉(zhuǎn)到頭,所以如果游絲損壞就會出現(xiàn)測量的時候指針偏轉(zhuǎn)幅度較大,或者是測量信號不準(zhǔn),就是由于游絲損壞,或游絲變形引起的故障。可以采取更換游絲,或換掉表頭排除故障。(換游絲比較麻煩所以最好更換表頭)
表頭維修講解: 故障3:指針偏轉(zhuǎn)幅度很小,如果出現(xiàn)測量信號的時候指針幾乎不偏轉(zhuǎn),排除保險管被燒斷的故障,排除萬用表內(nèi)部電池沒電,以及萬用表內(nèi)部電路中分壓分流電阻損壞,(內(nèi)部的分壓電阻和分流電阻不可能全部損壞),則故障肯定出現(xiàn)在表頭,重點檢查表頭,指針偏轉(zhuǎn)的幅度比較小的故障,一般在與表頭內(nèi)部磁鋼失磁引起的該故障發(fā)生,由于將指針萬用表長時間放在離磁場干擾能力強的地方,磁電式儀表的表頭內(nèi)部磁鋼失磁,引起該故障發(fā)生,可用充磁機給表頭充磁,當(dāng)然也可以采用更換表頭,淘寶網(wǎng)上我記得MF-47表頭是5塊錢。表頭故障維修: 故障4:指針偏轉(zhuǎn)的時候左右亂晃,這個故障其實很簡單,故障出現(xiàn)在表頭,是由于磁電式儀表內(nèi)部的指針阻尼器損壞,就是阻尼器損壞或阻尼器性能不良引起的該故障發(fā)生,可以采用更換新表頭來維修。表頭維修很簡單就這么幾個東西.指針偏轉(zhuǎn)幅度大或者測量不準(zhǔn)的話,多數(shù)就是游絲損壞,指針偏轉(zhuǎn)幅度小的話,多數(shù)就出現(xiàn)在磁鋼失磁或線圈燒斷引起的,而指針偏轉(zhuǎn)左右亂晃多數(shù)就是阻尼器損壞引起。
電路故障維修:
指針萬用表電路維修:故障1:輸入保險管250V/0.5A被燒斷引起沒有電流輸入,所有檔位無法使用(所有檔位測量時指針不動)的故障,這個故障算是在修萬用表中最簡單的了,由于使用失誤,用電流擋去測量電壓,或用電阻擋去測量電壓,引起的將輸入保險管被燒斷導(dǎo)致的沒有電流輸入故障,維修方法很簡單將萬用表拆開測下輸入保險管發(fā)現(xiàn)已經(jīng)被燒斷換掉一個同型號同規(guī)格保險管故障修復(fù)。47型指針萬用表 保險管規(guī)格為250V/0.5A 換掉一個新保險管故障修復(fù)。
指針萬用表電路維修:故障2:交流電壓擋中整流器中半波整流電路中的兩只整流二極管擊穿或開路引起交流電壓擋無法正常使用或測量不準(zhǔn)的故障,我們知道指針萬用表交流電壓擋測量原理:通過與表頭串聯(lián)電阻分壓來擴大交流電壓擋量程,在走半波整流電路將交流信號整流變?yōu)橹绷餍盘柫鬟^表頭來測量,因為指針萬用表的表頭是一個直流電流表表頭無法流過交流信號所以必須要在交流電壓擋中加上一個半波整流電路做整流器將交流信號整流變?yōu)橹绷餍盘柫鬟^表頭來測量,所以說測量一次交流電就要經(jīng)過整流二極管整流一次,如果長時間測量交流電的話,整流二極管由于經(jīng)常會被交流信號沖擊,一般會遇到開路或短路的情況這點是很常見的故障,所以說如果遇到指針萬用表交流電壓擋無法使用的故障,上來先檢查保險管,因為保險管被燒斷會引起沒有電流輸入表針肯定不會動的,如果萬用表保險管正常交流電壓擋還是無法使用,則要先檢查電刷與電路板轉(zhuǎn)換開關(guān)觸點是否接觸松動或接觸不良,排除接觸不良交流電壓擋還是無法正常使用,則要重點檢查交流電壓擋中的幾只分壓電阻,檢查分壓電阻有無阻值變化現(xiàn)象或開路現(xiàn)象,如果有就先換掉分壓電阻,排除分壓電阻有損壞,交流電壓擋還是無法正常使用,則應(yīng)該重點檢查交流電壓擋中的整流器中半波整流電路中的兩只整流二極管的正反向電阻值,可能是由于整流二極管擊穿或開路引起的交流電壓擋無法使用或測量不準(zhǔn)的故障,如果檢查中發(fā)現(xiàn)整流二極管有擊穿或開路的現(xiàn)象,更換同型號的管子來修復(fù)該故障。
指針萬用表電路維修: 故障3:電阻擋測量不準(zhǔn)以及電阻擋無法使用的故障,由于9V電池和1.5V電池電壓偏低引起該故障發(fā)生換新電池排除故障,電阻擋無法測量由于9V電池和1.5V電池接線有斷線或虛焊現(xiàn)象,檢查修復(fù)故障,電阻擋等效電阻有開路,轉(zhuǎn)換開關(guān)的電刷與電路板觸電接觸松動,引起電阻擋無法使用的故障。
指針萬用表電路維修: 故障4:電刷與電路板接觸松動,引起萬用表所有檔位無法使用,指針無法偏轉(zhuǎn),維修方法很簡單,將萬用表拆掉,從新安裝電刷,安裝電刷之前清理電路板。這個故障很簡單,由于電刷與電路板接觸不良引起。
指針萬用表電路維修:故障5:直流電流擋中分流電阻燒掉,引起電流擋無法使用,我們知道電流擋中分流電阻阻值都是比較小的,一般都是幾歐姆或幾十歐的分流電阻,如果使用失誤用電流擋去測量電壓,相當(dāng)于短路電源,產(chǎn)生短路電流直接將分流電阻燒掉,所以要檢查分流電阻好壞,這點應(yīng)該注意。
指針萬用表電路維修: 故障6:電阻擋所有檔位調(diào)零不準(zhǔn),檢查電池電壓是否偏低,檢查電池接線接線,排除這些電阻擋還是調(diào)零不準(zhǔn),檢查電阻擋等效電阻有無損壞,等效電阻如果正常,調(diào)零還不準(zhǔn)的話,通過測量表頭偏轉(zhuǎn)電流調(diào)節(jié)電位器,如果還是無法將指針歸0則就是歐姆調(diào)零電路的故障,首先檢查電阻調(diào)零電位器是否有虛焊或阻值變大的故障,如果電位器正常的話,則要檢查與電位器相連接的可調(diào)電阻,如果檢查可調(diào)電阻的時候,測出來可調(diào)電阻阻值明顯變大則說明故障就在這個地方,換掉可調(diào)電阻故障修復(fù),我們知道歐姆調(diào)零電路工作原理:電阻調(diào)零電位器接一個可調(diào)電阻,通過擰動電阻調(diào)零電位器相當(dāng)于改變可調(diào)電阻的電阻值從而改變流過表頭電流大小來進(jìn)行調(diào)零,如果說,可調(diào)電阻阻值變大或阻值變小則可調(diào)電阻不受電位器控制,也就無法調(diào)節(jié)流過表頭電流大小,從而出現(xiàn)的歐姆調(diào)零不準(zhǔn)的故障。
指針萬用表電路維修: 故障7:交直流電壓擋分壓電阻燒掉,我們知道電壓擋分壓電阻阻值都是比較大的,比如直流1000V接 10M分壓電阻 500V接5M 250V接4M 50V接800K 10V接150K 交流電壓擋1000V接2M 500V接1M 250V接800K 阻值都是比較大的不容易壞,容易壞的在10V量程以下的分壓電阻,如果使用失誤用10V量程以下的檔位去測量高電壓,一:輸入保險管肯定被燒斷,2:就是分壓電阻容易燒壞,這點應(yīng)該重點檢查。
第三篇:C++“指針”學(xué)習(xí)建議
一.對于眾多人提出的c/c++中指針難學(xué)的問題做個總結(jié):
指針學(xué)習(xí)不好關(guān)鍵是概念不清造成的,說的簡單點就是書沒有認(rèn)真看,指針的學(xué)習(xí)猶如人在學(xué)習(xí)饒口令不多看多學(xué)多練是不行的,下面是兩個很經(jīng)典的例子,很多書上都有,對于學(xué)習(xí)的重點在于理解*x和x的理解,他們并不相同,*x所表示的其實就是變量a本身,x表示的是變量a在內(nèi)存中的地址,如果想明白可以輸出觀察cout<<*x“|”x;,當(dāng)定義了int *x;后對x=&a的理解的問題。仔細(xì)閱讀和聯(lián)系下面的兩個例子我想指針問題就不是難點了!
#include
point_1=&a;/* 把指針變量point_1的值指向變量a的地址 */ point_2=&b;/* 把指針變量point_2的值指向變量b的地址 */ if(a main(){ int a,b;/* 定義a,b兩個整形變量用于輸入兩個整數(shù) */ int *point_1,*point_2;/* 定義三個指針變量 */ scanf(“%d,%d”,&a,&b);/* 格式化輸入a,b的值 */
point_1 = &a;/* 把指針變量point_1的值指向變量a的地址 */ point_2 = &b;/* 把指針變量point_2的值指向變量b的地址 */
compositor(point_1,point_2);/* 調(diào)用自定義的排序涵數(shù),把a,b的地址傳遞給point_1和point_2 */ printf(“%d,%d”,a,b);/* 打印出a,b的值 */ } static compositor(p1,p2)int *p1,*p2;/* 定義形式參數(shù)p1,p2為指針變量 */ { int temp;/* 建立臨時存儲變量 */
if(*p1<*p2)/* 如果*p1
*p1 = *p2;/* 將*p1的值也就是a的值換成*p2的值也就是b的值,等價于a=b */ *p2 = temp;/* 將*p2的值也就是temp的值等價于b=temp */ } } /* 注意:此題與上題不同的是,直接改變了a于b的值達(dá)到真實改變的目的 */
二.C++指針使用方法解惑
“void ClearList(LNode * & HL)”
仔細(xì)看一下這種聲明方式,確實有點讓人迷惑。
下面以void func1(MYCLASS *&pBuildingElement); 為例來說明這個問題。在某種意義上,“*”和“&”是意思相對的兩個東西,把它們放在一起有什么意義呢?。為了理解指針的這種做法,我們先復(fù)習(xí)一下C/C++編程中無所不在的指針概念。我們都知道MYCLASS*的意思:指向某個對象的指針,此對象的類型為MYCLASS。Void func1(MYCLASS *pMyClass);
// 例如: MYCLASS* p = new MYCLASS; func1(p);
上面這段代碼的這種處理方法想必誰都用過,創(chuàng)建一個MYCLASS對象,然后將它傳入func1函數(shù)。現(xiàn)在假設(shè)此函數(shù)要修改pMyClass: void func1(MYCLASS *pMyClass){ DoSomething(pMyClass); pMyClass = // 其它對象的指針 }
第二條語句在函數(shù)過程中只修改了pMyClass的值。并沒有修改調(diào)用者的變量p的值。如果p指向某個位于地址0x008a00的對象,當(dāng)func1返回時,它仍然指向這個特定的對象。(除非func1有bug將堆弄亂了,完全有這種可能。)
現(xiàn)在假設(shè)你想要在func1中修改p的值。這是你的權(quán)利。調(diào)用者傳入一個指針,然后函數(shù)給這個指針賦值。以往一般都是傳雙指針,即指針的指針,例如,CMyClass**。MYCLASS* p = NULL; func1(&p);
void func1(MYCLASS** pMyClass); { *pMyClass = new MYCLASS; ?? }
調(diào)用func1之后,p指向新的對象。在COM編程中,你到處都會碰到這樣的用法--例如在查詢對象接口的QueryInterface函數(shù)中: interface ISomeInterface { HRESULT QueryInterface(IID &iid, void** ppvObj); ?? };
LPSOMEINTERFACE p=NULL;
pOb->QueryInterface(IID_SOMEINTERFACE, &p);
此處,p是SOMEINTERFACE類型的指針,所以&p便是指針的指針,在QueryInterface返回的時候,如果調(diào)用成功,則變量p包含一個指向新的接口的指針。
如果你理解指針的指針,那么你肯定就理解指針引用,因為它們完全是一回事。如果你象下面這樣聲明函數(shù): void func1(MYCLASS *&pMyClass); { pMyClass = new MYCLASS; ?? } 其實,它和前面所講得指針的指針例子是一碼事,只是語法有所不同。傳遞的時候不用傳p的地址&p,而是直接傳p本身:
MYCLASS* p = NULL;
func1(p);
在調(diào)用之后,p指向一個新的對象。一般來講,引用的原理或多或少就象一個指針,從語法上看它就是一個普通變量。所以只要你碰到*&,就應(yīng)該想到**。也就是說這個函數(shù)修改或可能修改調(diào)用者的指針,而調(diào)用者象普通變量一樣傳遞這個指針,不使用地址操作符&。
至于說什么場合要使用這種方法,我會說,極少。MFC在其集合類中用到了它--例如,CObList,它是一個Cobjects指針列表。
Class CObList : public Cobject { ??
// 獲取/修改指定位置的元素
Cobject*& GetAt(POSITION position); Cobject* GetAt(POSITION position)const; };
這里有兩個GetAt函數(shù),功能都是獲取給定位置的元素。區(qū)別何在呢?
區(qū)別在于一個讓你修改列表中的對象,另一個則不行。所以如果你寫成下面這樣: Cobject* pObj = mylist.GetAt(pos);
則pObj是列表中某個對象的指針,如果接著改變pObj的值: pObj = pSomeOtherObj;
這并改變不了在位置pos處的對象地址,而僅僅是改變了變量pObj。但是,如果你寫成下面這樣: Cobject*& rpObj = mylist.GetAt(pos);
現(xiàn)在,rpObj是引用一個列表中的對象的指針,所以當(dāng)改變rpObj時,也會改變列表中位置pos處的對象地址--換句話說,替代了這個對象。這就是為什么CObList會有兩個GetAt函數(shù)的緣故。一個可以修改指針的值,另一個則不能。注意我在此說的是指針,不是對象本身。這兩個函數(shù)都可以修改對象,但只有*&版本可以替代對象。
在C/C++中引用是很重要的,同時也是高效的處理手段。所以要想成為C/C++高手,對引用的概念沒有透徹的理解和熟練的應(yīng)用是不行的。
三.?dāng)?shù)據(jù)指針
在C/C++語言中一直是很受寵的;幾乎找不到一個不使用指針的C/C++應(yīng)用。用于存儲數(shù)據(jù)和程序的地址,這是指針的基本功能。用于指向整型數(shù),用整數(shù)指針(int*);指向浮點數(shù)用浮點數(shù)指針(float*);指向結(jié)構(gòu),用對應(yīng)的結(jié)構(gòu)指針(struct xxx *);指向任意地址,用無類型指針(void*)。
有時候,我們需要一些通用的指針。在C語言當(dāng)中,(void*)可以代表一切;但是在C++中,我們還有一些比較特殊的指針,無法用(void*)來表示。事實上,在C++中,想找到一個通用的指針,特別是通用的函數(shù)指針簡直是一個“不可能任務(wù)”。
C++是一種靜態(tài)類型的語言,類型安全在C++中舉足輕重。在C語言中,你可以用void*來指向一切;但在C++中,void*并不能指向一切,就算能,也失去了類型安全的意義了。類型安全往往能幫我們找出程序中潛在的一些BUG。
下面我們來探討一下,C++中如何存儲各種類型數(shù)據(jù)的指針。
C++指針探討
(一)數(shù)據(jù)指針 沐楓網(wǎng)志
1.數(shù)據(jù)指針
數(shù)據(jù)指針分為兩種:常規(guī)數(shù)據(jù)指針和成員數(shù)據(jù)指針
1.1 常規(guī)數(shù)據(jù)指針
這個不用說明了,和C語言一樣,定義、賦值是很簡單明了的。常見的有:int*, double* 等等。
如:
int value = 123;int * pn = &value;
1.2 成員數(shù)據(jù)指針
有如下的結(jié)構(gòu): struct MyStruct { int key;int value;};
現(xiàn)在有一個結(jié)構(gòu)對象: MyStruct me;MyStruct* pMe = &me;
我們需要 value 成員的地址,我們可以: int * pValue = &me.value;//或
int * pValue = &pMe->value;
當(dāng)然了,這個指針仍然是屬于第一種范籌----常規(guī)數(shù)據(jù)指針。
好了,我們現(xiàn)在需要一種指針,它指向MyStruct中的任一數(shù)據(jù)成員,那么它應(yīng)該是這樣的子: int MyStruct::* pMV = &MyStruct::value;//或
int MyStruct::* pMK = &MyStruct::key;
這種指針的用途是用于取得結(jié)構(gòu)成員在結(jié)構(gòu)內(nèi)的地址。我們可以通過該指針來訪問成員數(shù)據(jù): int value = pMe->*pMV;// 取得pMe的value成員數(shù)據(jù)。
int key = me.*pMK;// 取得me的key成員數(shù)據(jù)。
那么,在什么場合下會使用到成員數(shù)據(jù)指針呢?
確實,成員指針本來就不是一種很常用的指針。不過,在某些時候還是很有用處的。我們先來看看下面的一個函數(shù): int sum(MyStruct* objs, int MyStruct::* pm, int count){ int result = 0;for(int i = 0;i < count;++i)result += objs[i].*pm;return result;}
這個函數(shù)的功能是什么,你能看明白嗎?它的功能就是,給定count個MyStruct結(jié)構(gòu)的指針,計算出給定成員數(shù)據(jù)的總和。有點拗口對吧?看看下面的程序,你也許就明白了:
MyStruct me[10] = { {1,2},{3,4},{5,6},{7,8},{9,10},{11,12},{13,14},{15,16},{17,18},{19,20} };int sum_value = sum(me, &MyStruct::value, 10);//計算10個MyStruct結(jié)構(gòu)的value成員的總和: sum_value 值 為 110(2+4+6+8+ int sum_key = sum(me, &MyStruct::key, 10);//計算10個MyStruct結(jié)構(gòu)的key成員的總和: sum_key 值 為 100(1+3+5+7+
+19)+20)也許,你覺得用常規(guī)指針也可以做到,而且更易懂。Ok,沒問題: int sum(MyStruct* objs, int count){ int result = 0;for(int i = 0;i < count;++i)result += objs[i].value;return result;}
你是想這么做嗎?但這么做,你只能計算value,如果要算key的話,你要多寫一個函數(shù)。有多少個成員需要計算的話,你就要寫多少個函數(shù),多麻煩啊。指針
四.C++指針使用
在下列函數(shù)聲明中,為什么要同時使用*和&符號?以及什么場合使用這種聲明方式?
void func1(MYCLASS *&pBuildingElement);論壇中經(jīng)常有人問到這樣的問題。
本文試圖通過一些實際的指針使用經(jīng)驗來解釋這個問題。
仔細(xì)看一下這種聲明方式,確實有點讓人迷惑。在某種意義上,“*”和“&”是意思相對的兩個東西,把它們放在一起有什么意義呢?。為了理解指針的這種做法,我們先復(fù)習(xí)一下C/C++編程中無所不在的指針概念。我們都知道MYCLASS*的意思:指向某個對象的指針,此對象的類型為MYCLASS。void func1(MYCLASS *pMyClass);
// 例如: MYCLASS* p = new MYCLASS;
func1(p);
上面這段代碼的這種處理方法想必誰都用過,創(chuàng)建一個MYCLASS對象,然后將它傳入func1函數(shù)。現(xiàn)在假設(shè)此函數(shù)要修改pMyClass: void func1(MYCLASS *pMyClass){ DoSomething(pMyClass);pMyClass = // 其它對象的指針 }
第二條語句在函數(shù)過程中只修改了pMyClass的值。并沒有修改調(diào)用者的變量p的值。如果p指向某個位于地址0x008a00的對象,當(dāng)func1返回時,它仍然指向這個特定的對象。(除非func1有bug將堆弄亂了,完全有這種可能。)
現(xiàn)在假設(shè)你想要在func1中修改p的值。這是你的權(quán)利。調(diào)用者傳入一個指針,然后函數(shù)給這個指針賦值。以往一般都是傳雙指針,即指針的指針,例如,CMyClass**。MYCLASS* p = NULL;func1(&p);void func1(MYCLASS** pMyClass);{ *pMyClass = new MYCLASS;?? }
調(diào)用func1之后,p指向新的對象。在COM編程中,你到處都會碰到這樣的用法--例如在查詢對象接口的QueryInterface函數(shù)中:
interface ISomeInterface { HRESULT QueryInterface(IID &iid, void** ppvObj);?? };
LPSOMEINTERFACE p=NULL;pOb->QueryInterface(IID_SOMEINTERFACE, &p);
此處,p是SOMEINTERFACE類型的指針,所以&p便是指針的指針,在QueryInterface返回的時候,如果調(diào)用成功,則變量p包含一個指向新的接口的指針。
如果你理解指針的指針,那么你肯定就理解指針引用,因為它們完全是一回事。如果你象下面這樣聲明函數(shù): void func1(MYCLASS *&pMyClass);{ pMyClass = new MYCLASS;?? } 其實,它和前面所講得指針的指針例子是一碼事,只是語法有所不同。傳遞的時候不用傳p的地址&p,而是直接傳p本身:
MYCLASS* p = NULL;func1(p);在調(diào)用之后,p指向一個新的對象。一般來講,引用的原理或多或少就象一個指針,從語法上看它就是一個普通變量。所以只要你碰到*&,就應(yīng)該想到**。也就是說這個函數(shù)修改或可能修改調(diào)用者的指針,而調(diào)用者象普通變量一樣傳遞這個指針,不使用地址操作符&。
至于說什么場合要使用這種方法,我會說,極少。MFC在其集合類中用到了它--例如,CObList,它是一個CObjects指針列表。
class CObList : public CObject { ??
// 獲取/修改指定位置的元素
CObject*& GetAt(POSITION position);CObject* GetAt(POSITION position)const;};這里有兩個GetAt函數(shù),功能都是獲取給定位置的元素。區(qū)別何在呢?
區(qū)別在于一個讓你修改列表中的對象,另一個則不行。所以如果你寫成下面這樣: CObject* pObj = mylist.GetAt(pos);
則pObj是列表中某個對象的指針,如果接著改變pObj的值: pObj = pSomeOtherObj;
這并改變不了在位置pos處的對象地址,而僅僅是改變了變量pObj。但是,如果你寫成下面這樣: CObject*& rpObj = mylist.GetAt(pos);
現(xiàn)在,rpObj是引用一個列表中的對象的指針,所以當(dāng)改變rpObj時,也會改變列表中位置pos處的對象地址--換句話說,替代了這個對象。這就是為什么CObList會有兩個GetAt函數(shù)的緣故。一個可以修改指針的值,另一個則不能。注意我在此說的是指針,不是對象本身。這兩個函數(shù)都可以修改對象,但只有*&版本可以替代對象。
在C/C++中引用是很重要的,同時也是高效的處理手段。所以要想成為C/C++高手,對引用的概念沒有透徹的理解和熟練的應(yīng)用是不行的。
五.新手學(xué)習(xí)之淺析c/c++中的指針
在學(xué)習(xí)c/c+過程中,指針是一個比較讓人頭痛的問題,稍微不注意將會是程序編譯無法通過,甚至造成死機。在程序設(shè)計過程中,指針也往往是產(chǎn)生隱含bug的原因。下面就來談?wù)勚羔樀膽?yīng)用以及需要注意的一些問題,里面也許就有你平時沒有注意到的問題,希望能幫助各位讀者理解好指針。
一、我們先來回憶一下指針的概念吧,方便下面的介紹
指針是存放地址值的變量或者常量。例如:int a=1;&a就表示指針常量(“&”表示取地址運算符,也即引用)。int *b,b表示的是指針變量(注意,是b表示指針變量而不是*b),*表示要說明的是指針變量。大家注意int *b[2]和int(*b)[2]是不同的,int *b表示一個指針數(shù)組,而int(*b)[2]表示含有兩個元素的int指針,這里要注意運算優(yōu)先級問題,有助于理解指針問題。在這里大概介紹基本概念就夠了,至于具體使用方法,如賦值等,很多書都有介紹,我就不多說了。
二、應(yīng)用以及注意的問題
1、理解指針的關(guān)鍵所在——對指針類型和指針?biāo)赶虻念愋偷睦斫?/p>
①、指針類型:可以把指針名字去掉,剩下的就是這個指針
例如: int *a;//指針類型為int *
int **a;//指針類型為int **
int *(*a)[8];//指針類型為 int *(*)[8]
②、指針?biāo)赶虻念愋停菏侵妇幾g器將把那一片內(nèi)存所看待成的類型。這里只要把指針聲明語句中的指針名字和名字右邊的“*”號去掉就可以了,剩下的就是指針?biāo)赶虻念愋汀?/p>
我之所以把他們放在第一位,是因為弄清楚他們是學(xué)c/c++指針的重點,正確理解他們才能使你打好c/c++的編程基礎(chǔ)。
2、指針的應(yīng)用——傳遞參數(shù)。
其實它可以相當(dāng)于隱式的返回值,這就比return的方法更加靈活了,可以返回更多的值,看看下面的例子自然就明白了:
#include “iostream.h”
void example(int *a1,int &b1,int c1)
{
*a1*=3;
++b1;
++c1;
}
void main()
{
int *a;
int b,c;
*a=6;
b=7;c=10;
example(a,b,c);
cout <<“*a=”<<*a<
cout <<“b=”<
cout <<“c=”<
}
輸出:*a=18
b=8
c=10
注意到?jīng)]有,*a和b的值都改變了,而c沒有變。這是由于a1是指向*a(=6)的指針,也即與a是指向同一個地址,所以當(dāng)a1指向的值改變了,*a的值也就改變了。在函數(shù)中的參數(shù)使用了引用(int &b1),b1是b的別名,也可以把它當(dāng)作特殊的指針來理解,所以b的值會改變。函數(shù)中的參數(shù)int c1只是在函數(shù)中起作用,當(dāng)函數(shù)結(jié)束時候便消失了,所以在main()中不起作用。
3、關(guān)于全局變量和局部變量的一個問題先不廢話了,先看看程序:
#include “iostream.h”
int a=5;
int *example1(int b)
{
a+=b;
return &a;
}
int *example2(int b)
{
int c=5;
b+=c;
return &b;
}
void main()
{
int *a1=example1(10);
int *b1=example2(10);
cout <<”a1=”<<*a1<
cout <<”b1=”<<*b1<
}
輸出結(jié)果:
a1=15
b1=4135
*b1怎么會是4135,而不是15呢?是程序的問題?沒錯吧?
由于a是全局變量,存放在全局變量的內(nèi)存區(qū),它一直是存在的;而局部變量則是存在于函數(shù)的棧區(qū),當(dāng)函數(shù)example2()調(diào)用結(jié)束后便消失,是b指向了一個不確定的區(qū)域,產(chǎn)生指針懸掛。
下面是對example1()和example2()的反匯編(用TC++ 3.0編譯):
example1():
push bp;入棧
mov bp,sp mov ax,[bp+04];傳遞參數(shù)
add [00AA],ax;相加
mov ax,00AA;返回了結(jié)果所在的地址
..pop bp;恢復(fù)棧,出棧
ret;退出函數(shù)
example2():
push bp;入棧
mov bp,sp
sub sp,02
mov word ptr [bp-02],0005
mov ax,[bp-02];傳遞參數(shù)
add [bp+04],ax;相加
lea ax,[bp+04];問題就出在這里
..mov sp,bp
pop bp;恢復(fù)棧,出棧
ret;退出函數(shù)
對比之后看出來了吧?ax應(yīng)該是存儲的是結(jié)果的地址。而在example2()中,返回的卻是[bp+04]的內(nèi)容,因此指針指向了一個不確定的地方,由此產(chǎn)生的指針懸掛。example1()中,ax返回了正確的結(jié)果的地址。
4、內(nèi)存問題:使用指針注意內(nèi)存的分配和邊界。使用指針過程中應(yīng)該給變量一個適當(dāng)?shù)目臻g,以免產(chǎn)生不可見的錯誤。請看以下代碼:
#include “iostream.h”
void main()
{
char *a1;
char *a2;
cin >>a1;
cin >>a2;
cout <<”a1=”<
cout <<”a2=”<
}
輸入:abc
123
輸出:
a1=123
a2=
Null pointer assignment
指針指向了“空”。解決辦法就是分配適當(dāng)?shù)膬?nèi)存給這兩個字符串。修正后的代碼
如下:
#include “iostream.h”
void main()
{
char *a1;
char *a2;
a1=new char [10];
a2=new char [10];
cin >>a1;
cin >>a2;
cout <<”a1=”<
cout <<”a2=”<
delete(a1);注意,別忘了要釋放內(nèi)存空間
delete(a2);
}
到此就能輸出正確的結(jié)果了。分配了適當(dāng)?shù)膬?nèi)存之后要注意釋放內(nèi)參空間,同時還應(yīng)該注意不要超出所分配的內(nèi)存的大小,否則會有溢出現(xiàn)象產(chǎn)生,導(dǎo)致不可預(yù)料的結(jié)果。
5、關(guān)于特殊的指針——引用
引用有時候應(yīng)用起來要比指針要靈活,用它做返回的時候是不產(chǎn)生任何變量的副本的這樣減小了內(nèi)存的占用,提高執(zhí)行的速度。引用使用起來要比指針好理解,比較直觀。當(dāng)引用作為參數(shù)時,不會改變參數(shù)的地址,因此可以作為左值。
下面請看一個例子:
#include “iostream.h”
char ch[5]=”ABCD”;
char &example(int b)
{
return ch;
}
void main()
{
cout <<”ch=”<
example(2)=”c”;
cout<<”ch=”<
}
輸出結(jié)果:
ch=ABCD
ch=ABcD
在實際編程過程中,可以靈活地引用或指針,盡量提高程序的可讀性和執(zhí)行效率。
三、小結(jié):
指針是學(xué)習(xí)c/c++的重點難點,主要原因是指針較為抽象,不容易理解。使用指針千萬要明白讓指針指向什么地方,如何讓指針指向正確的地方。在深入系統(tǒng)底層之中需要應(yīng)用到大量的指針,因此需要理解好指針的基本概念,例如:指針類型和指針?biāo)赶虻念愋汀F綍r應(yīng)該對留心觀察,了解程序的工作過程,必要時候可以對程序進(jìn)行反匯編,加深對指針的理解,這種方法同樣適合學(xué)別的編程方面的知識。
四、結(jié)束:
指針的應(yīng)用是很廣泛的,利用指針可以做很多事情,要成為一個好的程序員,必須對指針有比較深刻的了解。寫本文的目的在于讓大家對指針有更深一層的了解,提高指針的應(yīng)用能力,內(nèi)容大都是我在實際編程中遇到的問題。相信能給大家一定的幫助。
六.C++中關(guān)于指針入門的最好的文章
什么是指針?
其實指針就像是其它變量一樣,所不同的是一般的變量包含的是實際的真實的數(shù)據(jù),而指針是一個指示器,它告訴程序在內(nèi)存的哪塊區(qū)域可以找到數(shù)據(jù)。這是一個非常重要的概念,有很多程序和算法都是圍繞指針而設(shè)計的,如鏈表。
開始學(xué)習(xí)
如何定義一個指針呢?就像你定義一個其它變量一樣,只不過你要在指針名字前加上一個星號。我們來看一個例子:下面這個程序定義了兩個指針,它們都是指向整型數(shù)據(jù)。
int* pNumberOne;
int* pNumberTwo;
你注意到在兩個變量名前的“p”前綴了嗎?這是程序員通常在定義指針時的一個習(xí)慣,以提高便程序的閱讀性,表示這是個指針。現(xiàn)在讓我們來初始化這兩個指針:
pNumberOne = &some_number;
pNumberTwo = &some_other_number;
&號讀作“什么的地址”,它表示返回的是變量在內(nèi)存中的地址而不是變量本身的值。在這個例子中,pNumberOne 等于some_number的地址,所以現(xiàn)在pNumberOne指向some_number。如果現(xiàn)在我們在程序中要用到some_number,我們就可以使用pNumberOne。
我們來學(xué)習(xí)一個例子:
在這個例子中你將學(xué)到很多,如果你對指針的概念一點都不了解,我建議你多看幾遍這個例子,指針是個很復(fù)雜的東西,但你會很快掌握它的。
這個例子用以增強你對上面所介紹內(nèi)容的了解。它是用C編寫的(注:原英文版是用C寫的代碼,譯者重新用C++改寫寫了所有代碼,并在DEV C++ 和VC++中編譯通過!)
#include
void main()
{ // 聲明變量:
int nNumber;
int *pPointer;
// 現(xiàn)在給它們賦值:
nNumber = 15;
pPointer = &nNumber;
//打印出變量nNumber的值:
cout<<“nNumber is equal to :”<< nNumber< // 現(xiàn)在通過指針改變nNumber的值: *pPointer = 25; //證明nNumber已經(jīng)被上面的程序改變 //重新打印出nNumber的值: cout<<“nNumber is equal to :”< } 通讀一下這個程序,編譯并運行它,務(wù)必明白它是怎樣工作的。如果你完成了,準(zhǔn)備好,開始下一小節(jié)。 陷井! 試一下,你能找出下面這段程序的錯誤嗎? #include int *pPointer; void SomeFunction(); { int nNumber; nNumber = 25; //讓指針指向nNumber: pPointer = &nNumber; } void main() { SomeFunction();//為pPointer賦值 //為什么這里失敗了?為什么沒有得到25 cout<<“Value of *pPointer: ”<<*pPointer< } 這段程序先調(diào)用了SomeFunction函數(shù),創(chuàng)建了個叫nNumber的變量,接著讓指針pPointer指向了它。可是問題出在哪兒呢?當(dāng)函數(shù)結(jié)束后,nNumber被刪掉了,因為這一個局部變量。局部變量在定義它的函數(shù)執(zhí)行完后都會被系統(tǒng)自動刪掉。也就是說當(dāng)SomeFunction 函數(shù)返回主函數(shù)main()時,這個變量已經(jīng)被刪掉,但pPointer還指著變量曾經(jīng)用過的但現(xiàn)在已不屬于這個程序的區(qū)域。如果你還不明白,你可以再讀讀這個程序,注意它的局部變量和全局變量,這些概念都非常重要。 但這個問題怎么解決呢?答案是動態(tài)分配技術(shù)。注意這在C和C++中是不同的。由于大多數(shù)程序員都是用C++,所以我用到的是C++中常用的稱謂。 動態(tài)分配 動態(tài)分配是指針的關(guān)鍵技術(shù)。它是用來在不必定義變量的情況下分配內(nèi)存和讓指針去指向它們。盡管這么說可能會讓你迷惑,其實它真的很簡單。下面的代碼就是一個為一個整型數(shù)據(jù)分配內(nèi)存的例子: int *pNumber; pNumber = new int; 第一行聲明一個指針pNumber。第二行為一個整型數(shù)據(jù)分配一個內(nèi)存空間,并讓pNumber指向這個新內(nèi)存空間。下面是一個新例,這一次是用double雙精型: double *pDouble; pDouble = new double; 這種格式是一個規(guī)則,這樣寫你是不會錯的。 但動態(tài)分配又和前面的例子有什么不同呢?就是在函數(shù)返回或執(zhí)行完畢時,你分配的這塊內(nèi)存區(qū)域是不會被刪除的所以我們現(xiàn)在可以用動態(tài)分配重寫上面的程序: #include int *pPointer; void SomeFunction() { // 讓指針指向一個新的整型 pPointer = new int; *pPointer = 25; } void main() { SomeFunction();// 為pPointer賦值 cout<<“Value of *pPointer: ”<<*pPointer< } 通讀這個程序,編譯并運行它,務(wù)必理解它是怎樣工作的。當(dāng)SomeFunction調(diào)用時,它分配了一個內(nèi)存,并讓pPointer指向它。這一次,當(dāng)函數(shù)返回時,新的內(nèi)存區(qū)域被保留下來,所以pPointer始終指著有用的信息,這是因為了動態(tài)分配。但是你再仔細(xì)讀讀上面這個程序,雖然它得到了正確結(jié)果,可仍有一個嚴(yán)重的錯誤。 分配了內(nèi)存,別忘了回收 太復(fù)雜了,怎么會還有嚴(yán)重的錯誤!其實要改正并不難。問題是:你動態(tài)地分配了一個內(nèi)存空間,可它絕不會被自動刪除。也就是說,這塊內(nèi)存空間會一直存在,直到你告訴電腦你已經(jīng)使用完了。可結(jié)果是,你并沒有告訴電腦你已不再需要這塊內(nèi)存空間了,所以它會繼續(xù)占據(jù)著內(nèi)存空間造成浪費,甚至你的程序運行完畢,其它程序運行時它還存在。當(dāng)這樣的問題積累到一定程度,最終將導(dǎo)致系統(tǒng)崩潰。所以這是很重要的,在你用完它以后,請釋放它的空間,如: delete pPointer; 這樣就差不多了,你不得不小心。在這你終止了一個有效的指針(一個確實指向某個內(nèi)存的指針)。下面的程序,它不會浪費任何的內(nèi)存: #include int *pPointer; void SomeFunction() { // 讓指針指向一個新的整型 pPointer = new int; *pPointer = 25; } void main() { SomeFunction();//為pPointer賦值 cout<<“Value of *pPointer: ”<<*pPointer< delete pPointer; } 只有一行與前一個程序不同,但就是這最后一行十分地重要。如果你不刪除它,你就會制造一起“內(nèi)存漏洞”,而讓內(nèi)存逐漸地泄漏。(譯者:假如在程序中調(diào)用了兩次SomeFunction,你又該如何修改這個程序呢?請讀者自己思考) 傳遞指針到函數(shù) 傳遞指針到函數(shù)是非常有用的,也很容易掌握。如果我們寫一個程序,讓一個數(shù)加上5,看一看這個程序完整嗎?: #include void AddFive(int Number) { Number = Number + 5; } void main() { int nMyNumber = 18; cout<<“My original number is ”< AddFive(nMyNumber); cout<<“My new number is ”< } 問題出在函數(shù)AddFive里用到的Number是變量nMyNumber的一個副本而傳遞給函數(shù),而不是變量本身。因此,“ Number = Number + 5” 這一行是把變量的副本加了5,而原始的變量在主函數(shù)main()里依然沒變。試著運行這個程序,自己去體會一下。要解決這個問題,我們就要傳遞一個指針到函數(shù),所以我們要修改一下函數(shù)讓它能接受指針:把'void AddFive(int Number)' 改成 'void AddFive(int*Number)'。下面就是改過的程序,注意函數(shù)調(diào)用時要用&號,以表示傳遞的是指針: #include void AddFive(int* Number) { *Number = *Number + 5; } void main() { int nMyNumber = 18; cout 七.我眼中的指針--學(xué)習(xí)指針不可少的好文章 我眼中的指針--學(xué)習(xí)指針不可少的好文章 為初學(xué)者服務(wù)。這是我的帖子的宗旨。我也是個初學(xué)者(強調(diào)了無數(shù)遍了),我以我的理解把初學(xué)者覺得難懂的東西用淺顯的語言寫出來。由于小學(xué)時語文沒學(xué)好,所以竭盡全力也未必能達(dá)到這個目的。盡力而為吧。 指針是c和c++中的難點和重點。我只精通dos下的basic。c語言的其它各種特性,在basic中都有類似的東西。只有指針,是baisc所不具備的。指針是c的靈魂。 我不想重復(fù)大多數(shù)書上說得很清楚的東西,我只是把我看過的書中說得不清楚或沒有說,而我又覺得我理解得有點道理的東西寫出來。我的目的是: 1。通過寫這些東西,把我腦袋中關(guān)于c的模糊的知識清晰化。2。給初學(xué)者們一點提示。 3。賺幾個經(jīng)驗值。(因為貼這些東西沒有灌水之嫌啊) 第一章。指針的概念 指針是一個特殊的變量,它里面存儲的數(shù)值被解釋成為內(nèi)存里的一個地址。要搞清一個指針需要搞清指針的四方面的內(nèi)容:指針的類型,指針?biāo)赶虻念愋停羔樀闹祷蛘呓兄羔標(biāo)赶虻膬?nèi)存區(qū),還有指針本身所占據(jù)的內(nèi)存區(qū)。讓我們分別說明。先聲明幾個指針放著做例子: 例一:(1)int *ptr;(2)char *ptr;(3)int **ptr;(4)int(*ptr)[3];(5)int *(*ptr)[4];如果看不懂后幾個例子的話,請參閱我前段時間貼出的文?lt;<如何理解c和c++的復(fù)雜類型聲明>>。 1。指針的類型。 從語法的角度看,你只要把指針聲明語句里的指針名字去掉,剩下的部分就是這個指針的類型。這是指針本身所具有的類型。讓我們看看例一中各個指針的類型:(1)int *ptr;//指針的類型是int *(2)char *ptr;//指針的類型是char *(3)int **ptr;//指針的類型是 int **(4)int(*ptr)[3];//指針的類型是 int(*)[3](5)int *(*ptr)[4];//指針的類型是 int *(*)[4] 怎么樣?找出指針的類型的方法是不是很簡單? 2。指針?biāo)赶虻念愋汀?/p> 當(dāng)你通過指針來訪問指針?biāo)赶虻膬?nèi)存區(qū)時,指針?biāo)赶虻念愋蜎Q定了編譯器將把那片內(nèi)存區(qū)里的內(nèi)容當(dāng)做什么來看待。從語法上看,你只須把指針聲明語句中的指針名字和名字左邊的指針聲明符 * 去掉,剩下的就是指針?biāo)赶虻念愋汀@纾?/p> (1)int *ptr;//指針?biāo)赶虻念愋褪莍nt(2)char *ptr;//指針?biāo)赶虻牡念愋褪莄har(3)int **ptr;//指針?biāo)赶虻牡念愋褪?int *(4)int(*ptr)[3];//指針?biāo)赶虻牡念愋褪?int()[3](5)int *(*ptr)[4];//指針?biāo)赶虻牡念愋褪?int *()[4] 在指針的算術(shù)運算中,指針?biāo)赶虻念愋陀泻艽蟮淖饔谩V羔樀念愋?即指針本身的類型)和指針?biāo)赶虻念愋褪莾蓚€概念。當(dāng)你對C越來越熟悉時,你會發(fā)現(xiàn),把與指針攪和在一起的“類型”這個概念分成“指針的類型”和“指針?biāo)赶虻念愋汀眱蓚€概念,是精通指針的關(guān)鍵點之一。我看了不少書,發(fā)現(xiàn)有些寫得差的書中,就把指針的這兩個概念攪在一起了,所以看起書來前后矛盾,越看越糊涂。 3。指針的值,或者叫指針?biāo)赶虻膬?nèi)存區(qū)或地址。 指針的值是指針本身存儲的數(shù)值,這個值將被編譯器當(dāng)作一個地址,而不是一個一般的數(shù)值。在32位程序里,所有類型的指針的值都是一個32位整數(shù),因為32位程序里內(nèi)存地址全都是32位長。指針?biāo)赶虻膬?nèi)存區(qū)就是從指針的值所代表的那個內(nèi)存地址開始,長度為sizeof(指針?biāo)赶虻念愋?的一片內(nèi)存區(qū)。以后,我們說一個指針的值是XX,就相 當(dāng)于說該指針指向了以XX為首地址的一片內(nèi)存區(qū)域;我們說一個指針指向了某塊內(nèi)存區(qū)域,就相當(dāng)于說該指針的值是這塊內(nèi)存區(qū)域的首地址。 指針?biāo)赶虻膬?nèi)存區(qū)和指針?biāo)赶虻念愋褪莾蓚€完全不同的概念。在例一中,指針?biāo)赶虻念愋鸵呀?jīng)有了,但由于指針還未初始化,所以它所指向的內(nèi)存區(qū)是不存在的,或者說是無意義的。 以后,每遇到一個指針,都應(yīng)該問問:這個指針的類型是什么?指針指向的類型是什么?該指針指向了哪里? 4。指針本身所占據(jù)的內(nèi)存區(qū)。 指針本身占了多大的內(nèi)存?你只要用函數(shù)sizeof(指針的類型)測一下就知道了。在32位平臺里,指針本身占據(jù)了4個字節(jié)的長度。指針本身占據(jù)的內(nèi)存這個概念在判斷一個指針表達(dá)式是否是左值時很有用。 第二章。指針的算術(shù)運算 指針可以加上或減去一個整數(shù)。指針的這種運算的意義和通常的數(shù)值的加減運算的意義是不一樣的。例如: 例二: 1。char a[20];2。int *ptr=a;......3。ptr++;在上例中,指針ptr的類型是int*,它指向的類型是int,它被初始化為指向整形變量a。接下來的第3句中,指針ptr被加了1,編譯器是這樣處理的:它把指針ptr的值加上了sizeof(int),在32位程序中,是被加上了4。由于地址是用字節(jié)做單位的,故ptr所指向的地址由原來的變量a的地址向高地址方向增加了4個字節(jié)。 由于char類型的長度是一個字節(jié),所以,原來ptr是指向數(shù)組a的第0號單元開始的四個字節(jié),此時指向了數(shù)組a中從第4號單元開始的四個字節(jié)。我們可以用一個指針和一個循環(huán)來遍歷一個數(shù)組,看例子: 例三: 例三: int array[20];int *ptr=array;...//此處略去為整型數(shù)組賦值的代碼。...for(i=0;i<20;i++){(*ptr)++;ptr++; } 這個例子將整型數(shù)組中各個單元的值加1。由于每次循環(huán)都將 八.指針詳解 第一章。指針的概念 指針是一個特殊的變量,它里面存儲的數(shù)值被解釋成為內(nèi)存里的一個地址。 要搞清一個指針需要搞清指針的四方面的內(nèi)容:指針的類型,指針?biāo)赶虻念愋停羔樀闹祷蛘呓兄羔標(biāo)赶虻膬?nèi)存區(qū),還有指針本身所占據(jù)的內(nèi)存區(qū)。讓 我們分別說明。先聲明幾個指針放著做例子: 例一:(1)int*ptr;(2)char*ptr;(3)int**ptr;(4)int(*ptr)[3];(5)int*(*ptr)[4]; 1。指針的類型。 從語法的角度看,你只要把指針聲明語句里的指針名字去掉,剩下的部分就是這個指針的類型。這是指針本身所具有的類型。讓我們看看例一中各個指針的類型:(1)int*ptr;//指針的類型是int*(2)char*ptr;//指針的類型是char*(3)int**ptr;//指針的類型是int**(4)int(*ptr)[3];//指針的類型是int(*)[3](5)int*(*ptr)[4];//指針的類型是int*(*)[4] 怎么樣?找出指針的類型的方法是不是很簡單? 2。指針?biāo)赶虻念愋汀?/p> 當(dāng)你通過指針來訪問指針?biāo)赶虻膬?nèi)存區(qū)時,指針?biāo)赶虻念愋蜎Q定了編譯器將把那片內(nèi)存區(qū)里的內(nèi)容當(dāng)做什么來看待。從語法上看,你只須把指針聲明語句中的指針名字和名字左邊的指針聲明符 *去掉,剩下的就是指針?biāo)赶虻念愋汀@纾?/p> (1)int*ptr;//指針?biāo)赶虻念愋褪莍nt(2)char*ptr;//指針?biāo)赶虻牡念愋褪莄har(3)int**ptr;//指針?biāo)赶虻牡念愋褪莍nt*(4)int(*ptr)[3];//指針?biāo)赶虻牡念愋褪莍nt()[3](5)int*(*ptr)[4];//指針?biāo)赶虻牡念愋褪莍nt*()[4] 在指針的算術(shù)運算中,指針?biāo)赶虻念愋陀泻艽蟮淖饔谩?/p> 指針的類型(即指針本身的類型)和指針?biāo)赶虻念愋褪莾蓚€概念。當(dāng)你對C越來越熟悉時,你會發(fā)現(xiàn),把與指針攪和在一起的“類型”這個概念分成“指針的類型”和“指針?biāo)赶虻念愋汀眱蓚€概念,是精通指針的關(guān)鍵點之一。我看了不少書,發(fā)現(xiàn)有些寫得差的書中,就把指針的這兩個概念攪在一起了,所以看起書來前后矛盾,越看越糊涂。 3。指針的值,或者叫指針?biāo)赶虻膬?nèi)存區(qū)或地址。 指針的值是指針本身存儲的數(shù)值,這個值將被編譯器當(dāng)作一個地址,而不是一個一般的數(shù)值。在32位程序里,所有類型的指針的值都是一個32位整數(shù),因為32位程序里內(nèi)存地址全都是32位長。指針?biāo)赶虻膬?nèi)存區(qū)就是從指針的值所代表的那個內(nèi)存地址開始,長度為sizeof(指針?biāo)赶虻念愋?的一片內(nèi)存區(qū)。以后,我們說一個指針的值是XX,就相當(dāng)于說該指針指向了以XX為首地址的一片內(nèi)存區(qū)域;我們說一個指針指向了某塊內(nèi)存區(qū)域,就相當(dāng)于說該指針的值是這塊內(nèi)存區(qū)域的首地址。指針?biāo)赶虻膬?nèi)存區(qū)和指針?biāo)赶虻念愋褪莾蓚€完全不同的概念。在例一中,指針?biāo)赶虻念愋鸵呀?jīng)有了,但由于指針還未初始化,所以它所指向的內(nèi)存區(qū) 是不存在的,或者說是無意義的。以后,每遇到一個指針,都應(yīng)該問問:這個指針的類型是什么?指針指向的類型是什么?該指針指向了哪里? 4。指針本身所占據(jù)的內(nèi)存區(qū)。 指針本身占了多大的內(nèi)存?你只要用函數(shù)sizeof(指針的類型)測一下就知道了。在32位平臺里,指針本身占據(jù)了4個字節(jié)的長度。指針本身占據(jù)的內(nèi)存這個概念在判斷一個指針表達(dá)式是否是左值時很有用。第二章。指針的算術(shù)運算 指針可以加上或減去一個整數(shù)。指針的這種運算的意義和通常的數(shù)值的加減運算的意義是不一樣的。例如: 例二: 1。char a[20];2。int *ptr=a;......3。ptr++;在上例中,指針ptr的類型是int*,它指向的類型是int,它被初始化為指向整形變量a。接下來的第3句中,指針ptr被加了1,編譯器是這樣處理的:它把指針 ptr的值加上了sizeof(int),在32位程序中,是被加上了4。由于地址是用字節(jié)做單位的,故ptr所指向的地址由原來的變量a的地址向高地址方向增加了4個字節(jié)。 由于char類型的長度是一個字節(jié),所以,原來ptr是指向數(shù)組a的第0號單元開始的四個字節(jié),此時指向了數(shù)組a中從第4號單元開始的四個字節(jié)。我們可以用一個指針和一個循環(huán)來遍歷一個數(shù)組,看例子: 例三: int array[20];int *ptr=array;...//此處略去為整型數(shù)組賦值的代碼。...for(i=0;i<20;i++){(*ptr)++;ptr++; } 這個例子將整型數(shù)組中各個單元的值加1。由于每次循環(huán)都將指針ptr加1,所以每次循環(huán)都能訪問數(shù)組的下一個單元。再看例子: 例四: 1。char a[20];2。int *ptr=a;......3。ptr+=5;在這個例子中,ptr被加上了5,編譯器是這樣處理的:將指針ptr的值加上5乘sizeof(int),在32位程序中就是加上了5乘4=20。由于地址的單位是字節(jié),故現(xiàn)在的ptr所指向的地址比起加5后的ptr所指向的地址來說,向高地址方向移動了20個字節(jié)。在這個例子中,沒加5前的ptr指向數(shù)組a的第0號單元開始的四個字節(jié),加5后,ptr已經(jīng)指向了數(shù)組a的合法范圍之外了。雖然這種情況在應(yīng)用上會出問題,但在語法上卻是可以的。這也體現(xiàn)出了指針的靈活性。如果上例中,ptr是被減去5,那么處理過程大同小異,只不過ptr的值是被減去5乘sizeof(int),新的ptr指向的地址將比原來的ptr所指向的地址向低地址方向移動了20個字節(jié)。 總結(jié)一下,一個指針ptrold加上一個整數(shù)n后,結(jié)果是一個新的指針ptrnew,ptrnew的類型和ptrold的類型相同,ptrnew所指向的類型和ptrold所指向的類型也相同。ptrnew的值將比ptrold的值增加了n乘sizeof(ptrold所指向的類型)個字節(jié)。就是說,ptrnew所指向的內(nèi)存區(qū)將比ptrold所指向的內(nèi)存區(qū)向高地址方向移動了n乘sizeof(ptrold所指向的類型)個字節(jié)。一個指針ptrold減去一個整數(shù)n后,結(jié)果是一個新的指針ptrnew,ptrnew的類型和ptrold的類型相同,ptrnew所指向的類型和ptrold所指向的類型也相同。ptrnew的值將比ptrold的值減少了n乘sizeof(ptrold所指向的類型)個字節(jié),就是說,ptrnew所指向的內(nèi)存區(qū)將比ptrold所指向的內(nèi)存區(qū)向低地址方向移動了n乘sizeof(ptrold所指向的類型)個字節(jié)。 第三章。運算符&和* 這里&是取地址運算符,*是...書上叫做“間接運算符”。&a的運算結(jié)果是一個指針,指針的類型是a的類型加個*,指針?biāo)赶虻念愋褪莂的類型,指針?biāo)赶虻牡刂仿铮蔷褪莂的地址。*p的運算結(jié)果就五花八門了。總之*p的結(jié)果是p所指向的東西,這個東西有這些特點:它的類型是p指向的類型,它所占用的地址是p所指向的地址。例五: int a=12;int b;int *p;int **ptr;p=&a;//&a的結(jié)果是一個指針,類型是int*,指向的類型是int,指向的地址是a的地址。 *p=24;//*p的結(jié)果,在這里它的類型是int,它所占用的地址是p所指向的地址,顯然,*p就是變量a。 ptr=&p;//&p的結(jié)果是個指針,該指針的類型是p的類型加個*,在這里是int **。該指針?biāo)赶虻念愋褪莗的類型,這里是int*。該指針?biāo)赶虻牡刂肪褪侵羔榩自己的地址。 *ptr=&b;//*ptr是個指針,&b的結(jié)果也是個指針,且這兩個指針的類型和所指向的類型是一樣的,所以用&b來給*ptr賦值就是毫無問題的了。 **ptr=34;//*ptr的結(jié)果是ptr所指向的東西,在這里是一個指針,對這個指針再做一次*運算,結(jié)果就是一個int類型的變量。 第四章。指針表達(dá)式。 一個表達(dá)式的最后結(jié)果如果是一個指針,那么這個表達(dá)式就叫指針表達(dá)式。下面是一些指針表達(dá)式的例子: 例六: int a,b;int array[10];int *pa;pa=&a;//&a是一個指針表達(dá)式。 int**ptr=&pa;//&pa也是一個指針表達(dá)式。 *ptr=&b;//*ptr和&b都是指針表達(dá)式。 pa=array;pa++;//這也是指針表達(dá)式。例七: char*arr[20];char**parr=arr;//如果把arr看作指針的話,arr也是指針表達(dá)式 char*str;str=*parr;//*parr是指針表達(dá)式 str=*(parr+1);//*(parr+1)是指針表達(dá)式 str=*(parr+2);//*(parr+2)是指針表達(dá)式 由于指針表達(dá)式的結(jié)果是一個指針,所以指針表達(dá)式也具有指針?biāo)哂械乃膫€要素:指針的類型,指針?biāo)赶虻念愋停羔樦赶虻膬?nèi)存區(qū),指針自身占據(jù)的內(nèi)存。 好了,當(dāng)一個指針表達(dá)式的結(jié)果指針已經(jīng)明確地具有了指針自身占據(jù)的內(nèi)存的話,這個指針表達(dá)式就是一個左值,否則就不是一個左值。在例七中,&a不是一個左值,因為它還沒有占據(jù)明確的內(nèi)存。*ptr是一個左值,因為*ptr這個指針已經(jīng)占據(jù)了內(nèi)存,其實*ptr就是指針pa,既然pa已經(jīng)在內(nèi)存中有了自己的位置,那么*ptr當(dāng)然也有了自己的位置。 第五章。數(shù)組和指針的關(guān)系 數(shù)組的數(shù)組名其實可以看作一個指針。看下例: 例八: int array[10]={0,1,2,3,4,5,6,7,8,9},value;......value=array[0];//也可寫成:value=*array;value=array[3];//也可寫成:value=*(array+3);value=array[4];//也可寫成:value=*(array+4); 上例中,一般而言數(shù)組名array代表數(shù)組本身,類型是int [10],但如果把array看做指針的話,它指向數(shù)組的第0個單元,類型是int*,所指向的類型是數(shù)組單元的類型即int。因此*array等于0就一點也不奇怪了。同理,array+3是一個指向數(shù)組第3個單元的指針,所以*(array+3)等于3。其它依此類推。例九: char*str[3]={ “Hello,thisisasample!”, “Hi,goodmorning.”, “Helloworld” };chars[80]; strcpy(s,str[0]);//也可寫成strcpy(s,*str);strcpy(s,str[1]);//也可寫成strcpy(s,*(str+1));strcpy(s,str[2]);//也可寫成strcpy(s,*(str+2));上例中,str是一個三單元的數(shù)組,該數(shù)組的每個單元都是一個指針,這些指針各指向一個字符串。把指針數(shù)組名str當(dāng)作一個指針的話,它指向數(shù)組的第0號單元,它的類型是char**,它指向的類型是char*。*str也是一個指針,它的類型是char*,它所指向的類型是char,它指向的地址是字符串“Hello,thisisasample!”的第一個字符的地址,即''H''的地址。str+1也是一個指針,它指向數(shù)組的第1號單元,它的類型是char**,它指向的類型是char*。*(str+1)也是一個指針,它的類型是char*,它所指向的類型是char,它指向“Hi,goodmorning.”的第一個字符''H'',等等。下面總結(jié)一下數(shù)組的數(shù)組名的問題。聲明了一個數(shù)組TYPEarray[n],則數(shù)組名稱array就有了兩重含義:第一,它代表整個數(shù)組,它的類型是TYPE[n];第二,它是一個指針,該指針的類型是TYPE*,該指針指向的類型是TYPE,也就是數(shù)組單元的類型,該指針指向的內(nèi)存區(qū)就是數(shù)組第0號單元,該指針自己占有單獨的內(nèi)存區(qū),注意它和數(shù)組第0號單元占據(jù)的內(nèi)存區(qū)是不同的。該指針的值是不能修改的,即類似array++的表達(dá)式是錯誤的。在不同的表達(dá)式中數(shù)組名array可以扮演不同的角色。在表達(dá)式sizeof(array)中,數(shù)組名array代表數(shù)組本身,故這時sizeof函數(shù) 測出的是整個數(shù)組的大小。在表達(dá)式*array中,array扮演的是指針,因此這個表達(dá)式的結(jié)果就是數(shù)組第0號單元的值。sizeof(*array)測出的是數(shù)組單元的大小。表達(dá)式array+n(其中n=0,1,2,....。)中,array扮演的是指針,故array+n的結(jié)果是一個指針,它的類型是TYPE*,它指向的類型是TYPE,它指向數(shù)組第n號單元。故sizeof(array+n)測出的是指針類型的大小。例十: int array[10];int(*ptr)[10];ptr=&array;上例中ptr是一個指針,它的類型是int(*)[10],他指向的類型是int[10],我們用整個數(shù)組的首地址來初始化它。在語句ptr=&array中,array代表數(shù)組本身。 本節(jié)中提到了函數(shù)sizeof(),那么我來問一問,sizeof(指針名稱)測出的究竟是指針自身類型的大小呢還是指針?biāo)赶虻念愋偷拇笮。看鸢甘乔罢摺@纾?int(*ptr)[10];則在32位程序中,有: sizeof(int(*)[10])==4 sizeof(int[10])==40 sizeof(ptr)==4 實際上,sizeof(對象)測出的都是對象自身的類型的大小,而不是別的什么類型的大小。 第六章。指針和結(jié)構(gòu)類型的關(guān)系 可以聲明一個指向結(jié)構(gòu)類型對象的指針。例十一: struct MyStruct { int a;int b;int c;}MyStruct ss={20,30,40};//聲明了結(jié)構(gòu)對象ss,并把ss的三個成員初始化為20,30和40。MyStruct*ptr=&ss;//聲明了一個指向結(jié)構(gòu)對象ss的指針。它的類型是MyStruct*, //它指向的類型是MyStruct。 int *pstr=(int*)&ss;//聲明了一個指向結(jié)構(gòu)對象ss的指針。但是它的 //類型和它指向的類型和ptr是不同的。 請問怎樣通過指針ptr來訪問ss的三個成員變量? 答案: ptr->a;ptr->b;ptr->c;又請問怎樣通過指針pstr來訪問ss的三個成員變量? 答案: *pstr;//訪問了ss的成員a。*(pstr+1);//訪問了ss的成員b。 *(pstr+2)//訪問了ss的成員c。 呵呵,雖然我在我的MSVC++6.0上調(diào)式過上述代碼,但是要知道,這樣使用pstr來訪問結(jié)構(gòu)成員是不正規(guī)的,為了說明為什么不正規(guī),讓我們看看怎樣通過指針來訪問數(shù)組的各個單元: 例十二: int array[3]={35,56,37};int*pa=array;通過指針pa訪問數(shù)組array的三個單元的方法是: *pa;//訪問了第0號單元 *(pa+1);//訪問了第1號單元 *(pa+2);//訪問了第2號單元 從格式上看倒是與通過指針訪問結(jié)構(gòu)成員的不正規(guī)方法的格式一樣。所有的C編譯器在排列數(shù)組的單元時,總是把各個數(shù)組單元存放在連續(xù)的存儲區(qū)里,單元和單元之間沒有空隙。但在存放結(jié)構(gòu)對象的各個成員時,在某種編譯環(huán)境下,可能會需要字對齊或雙字對齊或者是別的什么對齊,需要在相鄰兩個成員之間加若干個“填充字節(jié)”,這就導(dǎo)致各個成員之間可能會有若干個字節(jié)的空隙。所以,在例十二中,即使*pstr訪問到了結(jié)構(gòu)對象ss的第一個成員變量a,也不能保證*(pstr+1)就一定能訪問到結(jié)構(gòu)成員b。因為成員a和成員b之間可能會有若干填充字節(jié),說不定*(pstr+1)就正好訪問到了這些填充字節(jié)呢。這也證明了指針的靈活性。要是你的目的就是想看看各個結(jié)構(gòu)成員之間到底有沒有填充字節(jié),嘿,這倒是個不錯的方法。通過指針訪問結(jié)構(gòu)成員的正確方法應(yīng)該是象例十二中使用指針ptr的方法。 第七章。指針和函數(shù)的關(guān)系 可以把一個指針聲明成為一個指向函數(shù)的指針。int fun1(char*,int);int(*pfun1)(char*,int);pfun1=fun1;........inta=(*pfun1)(“abcdefg”,7);//通過函數(shù)指針調(diào)用函數(shù)。 可以把指針作為函數(shù)的形參。在函數(shù)調(diào)用語句中,可以用指針表達(dá)式來作為實參。例十三: int fun(char*);int a;char str[]=“abcdefghijklmn”;a=fun(str);......int fun(char*s){ int num=0;while(*s!= ''
主站蜘蛛池模板:
久久精品国产亚洲一区二区|
日本肥老妇色xxxxx日本老妇|
国产激情久久久久影院老熟女免费|
亚洲最大中文字幕无码网站|
国产免费一区二区三区vr|
国产亚洲精品久久久久久大师|
亚洲色国产欧美日韩|
成人精品天堂一区二区三区|
别揉我奶头|
国产极品白嫩精品|
欧美又大又色又爽aaaa片|
精品区2区3区4区产品乱码9|
国产亚洲精品电影网站在线观看|
麻豆传传媒久久久爱|
欧美日韓性视頻在線|
中文字幕人妻被公上司喝醉506|
中文天堂在线www|
人妻在卧室被老板疯狂进入国产|
国产精品欧美一区二区三区|
97se狠狠狠狼鲁亚洲综合网|
国产精品成人影院在线|
2020国产精品香蕉在线观看|
乱码人妻一区二区三区|
亚洲欧美熟妇自拍色综合图片|
国产精品69人妻无码久久|
无码国产福利av私拍|
国产亚洲第一午夜福利合集|
亚洲中文字幕无码爆乳av|
亂倫近親相姦中文字幕|
国产欧美一区二区精品仙草咪|
怡红院精品久久久久久久高清|
麻豆果冻传媒精品一区|
国产国产国产国产系列|
无套内谢少妇免费|
精品成人免费一区二区不卡|
亚洲一区二区三区在线播放无码|
欧美va天堂va视频va在线|
蜜臀亚洲av无码精品国产午夜.|
亚洲人成电影在线观看网色|
久久久久亚洲av成人网人人网站|
三级国产三级在线|