天堂国产午夜亚洲专区-少妇人妻综合久久蜜臀-国产成人户外露出视频在线-国产91传媒一区二区三区

當(dāng)前位置:主頁 > 論文百科 > 英文數(shù)據(jù)庫 >

好東西PICC——C語言的點(diǎn)滴

發(fā)布時間:2017-03-03 15:22

  本文關(guān)鍵詞:C語言點(diǎn)滴,由筆耕文化傳播整理發(fā)布。



語言的點(diǎn)滴( C 語言的點(diǎn)滴(轉(zhuǎn)) 由于 icd2 是在線仿真所以回占用部分芯片資源,但連接器并不知道什么地址已經(jīng)被 icd2 占用,如 果碰巧分配了被 icd2 占用的資源, 回浪費(fèi)大家的調(diào)試時間, 那么如何讓連接器知道什么地址不能分配呢? 請參考以下方法

適用條件:在 mplab ide 環(huán)境集成 c 編譯器 + icd2 調(diào)試程序 1.使用 hitec

h c + icd2 選擇 compile for icd project->build options->project->picc global

以下這段話表達(dá)的意思也不很貼切: 光在中斷入口和出口處為了保護(hù)和恢復(fù)這些中間臨時變量就需要大量的開銷,嚴(yán)重影響中斷服務(wù)的效 率。其實(shí),在 picc 中,對中斷中使用的臨時變量,為了防止重入或覆蓋,干脆就是中斷專用 在我們的 中斷專用。 中斷專用 picc 編程中,臨時變量(或者說局部變量),都有其生存期,在生存期結(jié)束后,可被覆蓋。 但中斷函數(shù)中使用到的臨時變量卻與一般概念上的臨時變量有很大的區(qū)別。中斷函數(shù)中使用到的臨時 變量和中斷函數(shù)中不使用到的臨時變量不能占用同一地址。換言之,中斷和非中斷的臨時變量地址不得重 疊。 看一下下面的例程:(16f877a) #include "pic.h" unsigned char i,j,k; void fn1(void) { unsigned char s1[40]; s1[0]=1; }

void interrupt sample (void) { unsigned char s2[50]; s2[0]=1; fn1(); } void main(void) { }

1

說明:i,j,k-----三個全局變量 s1[40]----40 個中斷調(diào)用使用的臨時變量 s2[50]----50 個中斷中使用的臨時變量 保護(hù) w、status 和 pclath 用去三個內(nèi)存變量

從上面程序中可以看出,bank0 資源已經(jīng)耗盡。50+40+3+3=96。由于中斷使用了 93 個 ram,這樣中斷以外 就沒有可以使用的臨時變量了。也就是說中斷使用的臨時變量將不會被重入。

再看一下下面的例子: #include "pic.h" unsigned char i,j,k; void fn1(void) { unsigned char s1[20]; s1[0]=1; } void fn2(void) { unsigned char s3[20]; s3[0]=1; } void interrupt sample (void) { unsigned char s2[50]; s2[0]=1; fn1(); } void main(void) { fn2(); } 說明:i,j,k-----三個全局變量 s1[20]----20 個中斷調(diào)用使用的臨時變量 s2[50]----50 個中斷中使用的臨時變量 s3[20]----20 個非中斷使用的臨時變量 保護(hù) w、status 和 pclath 用去三個內(nèi)存變量
2

從上面的例子中也可以看出,中斷使用的臨時變量和中斷外使用的臨時變量不可重疊。 eyuge2 兄所說的 picc 自動保護(hù)現(xiàn)場,其實(shí)就是 picc 對中斷中使用的臨時變量實(shí)施“禁入”。也就是, 中斷內(nèi)可實(shí)施中斷內(nèi)臨時變量覆蓋;中斷外的臨時變量也可進(jìn)行覆蓋;但中斷內(nèi)外之間的臨時變量不可相 互覆蓋。 當(dāng)然為了防止重入,中斷中使用的函數(shù)不可在中斷外被調(diào)用。(picc 可自動實(shí)施重入檢查。) 大家來看一下具體的例子,用 pic16f887a 編譯下列程序。

第一次,中斷處理函數(shù)什么也不做。 #include "pic.h" unsigned int m,n; unsigned char i,j,k,l; void interrupt sample (void) { } void main(void) { } 因?yàn)椴贿M(jìn)行操作,中斷函數(shù)不需要進(jìn)行現(xiàn)場保護(hù),編譯后結(jié)果是直接返回。 0004 0009 retfie

第二次, 中斷處理函數(shù)增加一條對全局變量的操作。 void interrupt sample (void) { i++; } 編譯結(jié)果是: 0004 00f0 0005 0803 0006 0183 0007 00a8 0008 0183 0009 0aa0 000a 0828 000b 0083 000c 0ef0 000d 0e70 000e 0009 movwf movf clrf movwf clrf incf movf movwf swapf swapf retfie
3

saved_w 3,w 3 saved_status 3 _i saved_status,w 3 saved_w saved_w,w

從結(jié)果看,只保護(hù) w 和 status,不對全局變量進(jìn)行現(xiàn)場保護(hù)。

最后來看一個中斷處理函數(shù)中調(diào)用一個函數(shù) fn()的例子。 在 fn()函數(shù)中涉及全局變量和局部變量。 void fn(void) { char temp; temp=i+j; i=temp++; } void interrupt sample (void) { fn(); } 0004 0004 00f0 0005 0803 0006 0183 0007 00a9 0008 080a 0009 00aa 000a 018a 000b 120a 000c 118a 000d 27f9 000e 120a 000f 118a 0010 082a 0011 008a 0012 0012 0829 0013 0083 0014 0ef0 0015 0e70 0016 0009 isr int_entry movwf movf clrf movwf movf movwf clrf bcf bcf call bcf bcf movf movwf int_restore movf movwf swapf swapf retfie
4

saved_w 3,w 3 saved_status 10,w saved_pclath 10 pclath,0x4 pclath,0x3 fn pclath,0x4 pclath,0x3 saved_pclath,w 10

saved_status,w 3 saved_w saved_w,w

在第三個例子中,由于涉及到跨頁的問題,中斷函數(shù)為了能正確返回中斷發(fā)生處地址,對 pclath 進(jìn) 行保護(hù)。 從以上我們可以看出,無論是在中斷處理中使用的變量,還是在中斷處理中調(diào)用其它函數(shù)而使用的變 量,中斷函數(shù)都不會對其實(shí)行自動保護(hù)。 當(dāng)然中斷前的地址入棧是屬于硬件功能,不需要軟件中作出相 應(yīng)操作。

picc 與指針 1:指針?biāo)囊兀ㄟ@部分主要從網(wǎng)上搜索到的,還不錯): 指針的類型 指針?biāo)赶虻念愋?指針的值或者叫指針?biāo)赶虻膬?nèi)存區(qū) 指針本身所占據(jù)的內(nèi)存區(qū) 指針的類型。 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] 怎么樣?找出指針的類型的方法是不是很簡單? 指針?biāo)赶虻念愋汀?1 .2 指針?biāo)赶虻念愋汀?當(dāng)你通過指針來訪問指針?biāo)赶虻膬?nèi)存區(qū)時,指針?biāo)赶虻念愋蜎Q定了編譯器將把那片內(nèi)存區(qū)里的內(nèi) 容當(dāng)做什么來看待。 從語法上看,你只須把指針聲明語句中的指針名字和名字左邊的指針聲明符 *去掉, 剩下的就是指針?biāo)赶虻念愋。例如?(1)int *ptr; //指針?biāo)赶虻念愋褪?int (2)char *ptr; //指針?biāo)赶虻牡念愋褪?char (3)int **ptr; //指針?biāo)赶虻牡念愋褪?int * (4)int (*ptr)[3]; //指針?biāo)赶虻牡念愋褪?int()[3] (5)int *(*ptr)[4]; //指針?biāo)赶虻牡念愋褪?int *()[4] 在指針的算術(shù)運(yùn)算中,指針?biāo)赶虻念愋陀泻艽蟮淖饔。指針的類?即指針本身的類型)和指針?biāo)?指向的類型是兩個概念。當(dāng)你對 c 越 來越熟悉時,你會發(fā)現(xiàn),把與指針攪和在一起的"類型"這個概念分 成"指針的 類型"和"指針?biāo)赶虻念愋?quot;兩個概念,是精通指針的關(guān)鍵點(diǎn)之一。 指針的值,或者叫指針?biāo)赶虻膬?nèi)存區(qū)或地址。 1.3 指針的值,或者叫指針?biāo)赶虻膬?nèi)存區(qū)或地址。 指針的值是指針本身存儲的數(shù)值,這個值將被編譯器當(dāng)作一個地址,而不是 一個一般的數(shù)值。在 32 位程序里,所有類型的指針的值都是一個 32 位整數(shù),因?yàn)?32 位程序里內(nèi)存地址全都是 32 位長。 指針?biāo)?br />5

指向的內(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)該問問:這 個指針的類型是什么?指針指向的 類型是什么?該指針指向了哪里? 1.4 指針本身所占據(jù)的內(nèi)存區(qū)。 指針本身所占據(jù)的內(nèi)存區(qū)。 指針本身占了多大的內(nèi)存?你只要用函數(shù) sizeof(指針的類型)測一下就知道了。在 32 位平臺里,指針 本身占據(jù)了 4 個字節(jié)的長度。 指針本身占據(jù)的內(nèi)存這個概念在判斷一個指針表達(dá)式是否是左值時很有用。 (注釋:在 picc18 里,指針占用了兩個字節(jié)) int data[10]={1,2,4,5,6,7,8}; int lenth1,lenth2,lenth3; int *ptr1,*ptr2; main() { ptr1=&data[0]; ptr2=&data[1]; lenth1=ptr2-ptr1; lenth2=(int)ptr2-(int)ptr1; lenth3=*ptr2-*ptr1; } 在 watch 窗口可以看到 lenth1 為 1,而 lenth2 為 2,可以這樣解釋:在 lenth1=ptr2-ptr1;這條語句中 兩個 int 類型指針變量相減得一個(這在 c 中是允許的)非指針的數(shù),這個數(shù)的代表如下: 如果這兩個指針指向的內(nèi)型為 int 型,那么這個數(shù)代表兩個指針之間相隔多少個 int 型變量,顯然在以上 程序中,data[0],和 data[1]之間相隔了 1 個 int 型變量而在 lenth2=(int)ptr2-(int)ptr1;實(shí)際上是求 data[1]和 data[0]之間占用多少個內(nèi)存空間,注意(int)ptr 是 ptr 的值(不是 ptr 所指向的數(shù)的值) lenth3=*ptr2-*ptr1;相信稍微懂 c 的人都知道是在求 ptr 所指向的兩個值之間的差,和 lenth3=data[1]-data[0]等效大家不防試試 lenth4=(char*)ptr2-(char*)ptr1;看看等于多少, 2: 指針函數(shù)和函數(shù)指針有什么區(qū)別 2.1,這兩個概念都是簡稱,指針函數(shù)是指帶指針的函數(shù),即本質(zhì)是一個函數(shù)。我們知道函數(shù)都又返 回類型(如果不返回值,則為無值型),只不過指針函數(shù)返回類型是某一類型的指針。其定義格式如下所 示: 返回類型標(biāo)識符 *返回名稱(形式參數(shù)表) { 函數(shù)體 } 返回類型可以是任何基本類型和復(fù)合類型。返回指針的函數(shù)的用途十分廣泛。事實(shí)上,每一個函 數(shù),即使它不帶有返回某種類型的指針,它本身都有一個入口地址,該地址相當(dāng)于一個指針。比如函數(shù)
6

下面就 picc18 列舉個實(shí)例看下面程序

返回一個整型值,實(shí)際上也相當(dāng)于返回一個指針變量的值,不過這時的變量是函數(shù)本身而已,而整個函 數(shù)相當(dāng)于一個“變量”。例如下面一個返回指針函數(shù)的例子: char data[10];

char* test(void); main() { char *ptr; ptr=test(); } char* test(void) { char *p; p=data; return p; } 注意:該程序在 picc18 中調(diào)試 2.2,“函數(shù)指針”是指向函數(shù)的指針變量,因而“函數(shù)指針”本身首先應(yīng)是指針變量,只不過該指針變量 指向函數(shù)。這正如用指針變量可指向整型變量、字符型、數(shù)組一樣,這里是指向函數(shù)。如前所述,c 在編 譯時,每一個函數(shù)都有一個入口地址,該入口地址就是函數(shù)指針?biāo)赶虻牡刂。有了指向函?shù)的指針變量 后,可用該指針變量調(diào)用函數(shù),就如同用指針變量可引用其他類型變量一樣,在這些概念上一致的。函數(shù) 指針有兩個用途:調(diào)用函數(shù)和做函數(shù)的參數(shù)。函數(shù)指針的說明方法為: 數(shù)據(jù)類型標(biāo)志符 (*指針變量名)(參數(shù));注:函數(shù)括號中的參數(shù)可有可無,視情況而定。 下面的程序說明了函數(shù)指針調(diào)用函數(shù)的方法: char max(char x,char y); char min(char x,char y); char (*ptr)(char,char); char a=2,b=3,c; main() { ptr=max; c=(*ptr)(a,b); ptr=min; c=(*ptr)(a,b); } char max(char x,char y) {
7

return x>=y?x:y; } char min(char x,char y) { return x<=y?x:y; } 注意:該程序在 picc18 中調(diào)試 在 pic 的 c 程序編寫中,函數(shù)指針不是很常用,如果大家有興趣看看 ucos 的 pic18 的移植版本,就可以 發(fā)現(xiàn) ucos 中是用函數(shù)指針傳遞任務(wù)程序的入口地址的。

3:結(jié)構(gòu)聯(lián)合與指針 先看下面的一個簡單的舉例 typedef struct datas { char datah; char datal; struct datas *next; } data; //a 是一個結(jié)構(gòu)變量 data a,b; data *ptr1,*ptr2; main() { ptr1=&a; ptr1->datah =1; ptr1->datal =2; ptr2=&b; ptr1->datah =3; ptr1->datal =4; ptr1->next=ptr2; ptr2->next=0; } 數(shù)據(jù) a,b 是一個結(jié)構(gòu)型變量,ptr 則是指向結(jié)構(gòu)型變量的指針,在 c 語言里,通過形如 ptr->x 的形式來 訪問結(jié)構(gòu)或者指針的成員。在結(jié)構(gòu)變量中定義了一個指針 struct datas *next; 這是在指針鏈中常用到 的,ptr1->next=ptr2; ptr2->next=0;實(shí)際上已經(jīng)建立了一條簡單的指針鏈,當(dāng)然建立指針鏈用這種初始 化的方法不夠簡單,但是上面的程序只是為了說明指針和結(jié)構(gòu)而已。
8

在單片機(jī)的 c 語言程序中,聯(lián)合和結(jié)構(gòu)是經(jīng)常用在一起的下面在舉一個簡單的列子: typedef struct { char datah; char datal;

} data; typedef union { data int twpbyte; bytes;

} piccdata; piccdata adres[10]; piccdata *ptr1,*ptr2; char lenth1,lenth2; main() { ptr2=adres; ptr1=adres; ptr1++; lenth1=ptr1-ptr2; lenth2=(char)ptr1-(char)ptr2;

} 在以上程序中,lenth2 為 2,而 lenth1 為 1,道理和第一個列子一樣,只是應(yīng)該注意的是在 piccdata 型 變量中占用的空間為 2 個字節(jié)而不是 4 個字節(jié)!。 另:結(jié)構(gòu)與聯(lián)合是 pic 應(yīng)用的一個好東西,這點(diǎn) hotpower 曾經(jīng)有一很經(jīng)典的文章,在此列中,只要稍微 加以改動,就可以對一個 16 位變量即可以整體訪問,也可分為高八位訪問和低八位訪問。這在 ad 轉(zhuǎn)換中 是很有用的。 4: const 與指針 如果 const 關(guān)鍵字不涉及到指針,我

const 是一個 c 語言的關(guān)鍵字,它限定一個變量不允許被改變。 們很好理解,下面是涉及到指針的情況: int b = 500; const int* a = &b; int const *a = &b; int* const a = &b; [1] [2] [3]
9

const int* const a = &b;

[4]

如果 const 位于星號的左側(cè),則 const 就是用來修飾指針?biāo)赶虻淖兞,即指針指向(yàn)槌A浚蝗绻?const 位于星號的右側(cè),const 就是修飾指針本身,即指針本身是常量。因此,[1]和[2]的情況相同,都是指針 所指向的內(nèi)容為常量(const 放在變量聲明符的位置無關(guān)),這種情況下不允許對內(nèi)容進(jìn)行更改操作,如 不能*a = 3 ;[3]為指針本身是常量,而指針?biāo)赶虻膬?nèi)容不是常量,這種情況下不能對指針本身進(jìn)行更 改操作,如 a++是錯誤的;[4]為指針本身和指向的內(nèi)容均為常量。有了上面的基礎(chǔ),對于在 picc18 中的 c 語言應(yīng)用就可以開始了,在單片機(jī)編程中,經(jīng)常會用到查表程序等,通常把大量的數(shù)據(jù)放入 rom 中,下 面是一個簡單的列子

const int a[8]={1,2,3,-3,3,5,6,7}; const int *ptr; main() { ptr=a; ptr++; } 顯然 ptr 是一個指向常量的指針,ptr 指向的數(shù)是不可變的,,但是 ptr 本身是可變的,我們可以通過 ptr 來訪問定義在 rom 中的數(shù)組 a[8]; 歡迎補(bǔ)充和指正,謝謝! 讀寫片內(nèi) eeprom 數(shù)據(jù)區(qū),每一本相關(guān)的數(shù)據(jù)手冊都有詳細(xì)的例程,抄上去就可以了。如果連抄上也不行, 那你還有什么是可以的呢? 什么都想要現(xiàn)成的,自己一點(diǎn)主觀的進(jìn)取心都沒有。你要用 c 寫程序,這當(dāng)然是好事,可是連現(xiàn)成的匯編 語句都無法用 c 語言復(fù)述一遍,那你還能用 c 寫出什么有用的代碼? 自己如果不清楚,就不要瞎說。什么“不是將 wr 置 1,寫完后會自動將 wr 置 1”:事實(shí)正好相反。 可能又要說是初學(xué)之類的借口了。那反問一句:這象認(rèn)真學(xué)習(xí)的模樣嗎? 算了,附上一些代碼吧,僅供參考。 //============================================================= //write a byte of data into eeprom memory //input: // // eedata - data to be written eeaddr - eeprom memory address

//return: // // // 0 - successful 1 - data error 2 - time out
10

//=============================================================

unsigned char ee_write(void) { unsigned char tmpdata; eeif = 0; eedata = eedata; eeadr = eeaddr; eepgd = 0; wren gie = 1; = 0; //data to write //adress to write //point to ee area //ee write enabled //no interrupt following //password 55 //password aa //internal ee write cycle begin now //ee write can be disabled //interrupt could be enabled //for backgound time-out control

eecon2 = 0x55; eecon2 = 0xaa; wr wren gie = 1; = 0; = 1;

timer = 10; do {

asm("clrwdt"); } while (eeif==0 && timer!=0); //wait for ee write completed or time-out if (eeif==1 && timer!=0) { tmpdata = eedata; ee_read(); //read back the written data //verify //ee write completed normally

if (tmpdata == eedata) return(0); else return(1); } else return(2); }

//data is good

//data is corrupted

//ww write time out

//============================================================= //read a byte of data from eeprom memory //input: // eeaddr - eeprom memory address

//output // eedata - data read

//============================================================= void ee_read(void)
11

{ eedata = 0xff; eeadr = eeaddr; eepgd = 0; rd = 1;

eedata = eedata; }

12

深入理解 C 語言指針的奧秘 指針的概念 例三:

intarray[20]; int*ptr=array; ... //此處略去為整型數(shù)組賦值的代碼。 ... for(i=0;ia; 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ù)組的各個單元: 例十二:

intarray[3]={35,56,37}; int*pa=array; 通過指針 pa 訪問數(shù)組 array 的三個單元的方法是: *pa;//訪問了第 0 號單元 *(pa+1);//訪問了第 1 號單元 *(pa+2);//訪問了第 2 號單元 從格式上看倒是與通過指針訪問結(jié)構(gòu)成員的不正規(guī)方法的格式一樣。 所有的 C/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。因?yàn)槌蓡T a 和成員 b 之間可能會有若干填充字節(jié),說不 定*(pstr+1)就正好訪問到了這些填充字節(jié)呢。這也證明了指針的靈活性。要是你的目的就是想看看各個結(jié)構(gòu)成員之間到底有沒有填充字節(jié),嘿,這倒是個不錯的方法。 通過指針訪問結(jié)構(gòu)成員的正確方法應(yīng)該是象例十二中使用指針 ptr 的方法。 指針和函數(shù)的關(guān)系 可以把一個指針聲明成為一個指向函數(shù)的指針。

intfun1(char*,int); int(*pfun1)(char*,int);

13

pfun1=fun1; .... .... inta=(*pfun1)("abcdefg",7);//通過函數(shù)指針調(diào)用函數(shù)。 例十三: 可以把指針作為函數(shù)的形參。在函數(shù)調(diào)用語句中,可以用指針表達(dá)式來作為實(shí)參。

intfun(char*); inta; charstr[]="abcdefghijklmn"; a=fun(str); ... ... intfun(char*s) { intnum=0; for(inti=0;i{ num+=*s;s++; } returnnum; } 這個例子中的函數(shù) fun 統(tǒng)計一個字符串中各個字符的 ASCII 碼值之和。前面說了,數(shù)組的名字也是一個指針。在函數(shù)調(diào)用中,當(dāng)把 str 作為實(shí)參傳遞給形參 s 后,實(shí)際是把 str 的值 傳遞給了 s,s 所指向的地址就和 str 所指向的地址一致,但是 str 和 s 各自占用各自的存儲空間。在函數(shù)體內(nèi)對 s 進(jìn)行自加 1 運(yùn)算,并不意味著同時對 str 進(jìn)行了自加 1 運(yùn)算。 指針類型轉(zhuǎn)換 當(dāng)我們初始化一個指針或給一個指針賦值時,賦值號的左邊是一個指針,賦值號的右邊是一個指針表達(dá)式。在我們前面所舉的例子中,絕大多數(shù)情況下,指針的類型和指針表達(dá)式 的類型是一樣的,指針?biāo)赶虻念愋秃椭羔槺磉_(dá)式所指向的類型是一樣的。 例十四: 1、floatf=12.3; 2、float*fptr=&f; 3、int*p; 在上面的例子中,假如我們想讓指針 p 指向?qū)崝?shù) f,應(yīng)該怎么搞?是用下面的語句嗎? p=&f; 不對。因?yàn)橹羔?p 的類型是 int*,它指向的類型是 int。表達(dá)式&f 的結(jié)果是一個指針,指針的類型是 float*,它指向的類型是 float。兩者不一致,直接賦值的方法是不行的。至少在 我的 MSVC++6.0 上,對指針的賦值語句要求賦值號兩邊的類型一致,所指向的類型也一致,其它的編譯器上我沒試過,大家可以試試。為了實(shí)現(xiàn)我們的目的,需要進(jìn)行"強(qiáng)制類型轉(zhuǎn)換": p=(int*)&f; 如果有一個指針 p,我們需要把它的類型和所指向的類型改為 TYEP*TYPE, 那么語法格式是: (TYPE*)p; 沒有被修改。 這樣強(qiáng)制類型轉(zhuǎn)換的結(jié)果是一個新指針,該新指針的類型是 TYPE*,它指向的類型是 TYPE,它指向的地址就是原指針指向的地址。而原來的指針 p 的一切屬性都

14

一個函數(shù)如果使用了指針作為形參,那么在函數(shù)調(diào)用語句的實(shí)參和形參的結(jié)合過程中,也會發(fā)生指針類型的轉(zhuǎn)換。 例十五:

voidfun(char*); inta=125,b; fun((char*)&a); ... ... voidfun(char*s) { charc; c=*(s+3);*(s+3)=*(s+0);*(s+0)=c; c=*(s+2);*(s+2)=*(s+1);*(s+1)=c; } } 注意這是一個 32 位程序,故 int 類型占了四個字節(jié),char 類型占一個字節(jié)。函數(shù) fun 的作用是把一個整數(shù)的四個字節(jié)的順序來個顛倒。注意到了嗎?在函數(shù)調(diào)用語句中,實(shí)參&a 的結(jié)果是一個指針,它的類型是 int*,它指向的類型是 int。形參這個指針的類型是 char*,它指向的類型是 char。這樣,在實(shí)參和形參的結(jié)合過程中,我們必須進(jìn)行一次從 int*類型到 c har*類型的轉(zhuǎn)換。結(jié)合這個例子,我們可以這樣來想象編譯器進(jìn)行轉(zhuǎn)換的過程:編譯器先構(gòu)造一個臨時指針 char*temp, 然后執(zhí)行 temp=(char*)&a,最后再把 temp 的值傳遞給 s。所 以最后的結(jié)果是:s 的類型是 char*,它指向的類型是 char,它指向的地址就是 a 的首地址。 我們已經(jīng)知道,指針的值就是指針指向的地址,在 32 位程序中,指針的值其實(shí)是一個 32 位整數(shù)。那可不可以把一個整數(shù)當(dāng)作指針的值直接賦給指針呢?就象下面的語句: unsignedinta; TYPE*ptr;//TYPE 是 int,char 或結(jié)構(gòu)類型等等類型。 ... ... a=20345686; ptr=20345686;//我們的目的是要使指針 ptr 指向地址 20345686(十進(jìn)制 ) ptr=a;//我們的目的是要使指針 ptr 指向地址 20345686(十進(jìn)制) 編譯一下吧。結(jié)果發(fā)現(xiàn)后面兩條語句全是錯的。那么我們的目的就不能達(dá)到了嗎?不,還有辦法:

unsignedinta; TYPE*ptr;//TYPE 是 int,char 或結(jié)構(gòu)類型等等類型。 ... ... a=某個數(shù),這個數(shù)必須代表一個合法的地址; ptr=(TYPE*)a;//呵呵,這就可以了。 嚴(yán)格說來這里的(TYPE*)和指針類型轉(zhuǎn)換中的(TYPE*)還不一樣。這里的(TYPE*)的意思是把無符號整數(shù) a 的值當(dāng)作一個地址來看待。上面強(qiáng)調(diào)了 a 的值必須代表一個合法的地址,否 則的話,在你使用 ptr 的時候,就會出現(xiàn)非法操作錯誤。

15

想想能不能反過來,把指針指向的地址即指針的值當(dāng)作一個整數(shù)取出來。完 全可以。下面的例子演示了把一個指針的值當(dāng)作一個整數(shù)取出來,然后再把這個整數(shù)當(dāng)作一個地址賦給 一個指針: 例十六:

inta=123,b; int*ptr=&a; char*str; b=(int)ptr;//把指針 ptr 的值當(dāng)作一個整數(shù)取出來。 str=(char*)b;//把這個整數(shù)的值當(dāng)作一個地址賦給指針 str。 現(xiàn)在我們已經(jīng)知道了,可以把指針的值當(dāng)作一個整數(shù)取出來,也可以把一個整數(shù)值當(dāng)作地址賦給一個指針。 指針的安全問題 看下面的例子: 例十七:

chars='a'; int*ptr; ptr=(int*)&s; *ptr=1298; 指針 ptr 是一個 int*類型的指針,它指向的類型是 int。它指向的地址就是 s 的首地址。在 32 位程序中,s 占一個字節(jié),int 類型占四個字節(jié)。最后一條語句不但改變了 s 所占的一個 字節(jié),還把和 s 相臨的高地址方向的三個字節(jié)也改變了。這三個字節(jié)是干什么的?只有編譯程序知道,而寫程序的人是不太可能知道的。也許這三個字節(jié)里存儲了非常重要的數(shù)據(jù),也 許這三個字節(jié)里正好是程序的一條代碼,而由于你對指針的馬虎應(yīng)用,這三個字節(jié)的值被改變了!這會造成崩潰性的錯誤。 讓我們再來看一例: 例十八: 1、chara; 2、int*ptr=&a; ... ... 3、ptr++; 4、*ptr=115; 該例子完全可以通過編譯,并能執(zhí)行。但是看到?jīng)]有?第 3 句對指針 ptr 進(jìn)行自加 1 運(yùn)算后,ptr 指向了和整形變量 a 相鄰的高地址方向的一塊存儲區(qū)。這塊存儲區(qū)里是什么?我們 不知道。有可能它是一個非常重要的數(shù)據(jù),甚至可能是一條代碼。而第 4 句竟然往這片存儲區(qū)里寫入一個數(shù)據(jù)!這是嚴(yán)重的錯誤。所以在使用指針時,程序員心里必須非常清楚:我的 指針究竟指向了哪里。在用指針訪問數(shù)組的時候,也要注意不要超出數(shù)組的低端和高端界限,否則也會造成類似的錯誤。 在指針的強(qiáng)制類型轉(zhuǎn)換:ptr1=(TYPE*)ptr2 中,如果 sizeof(ptr2 的類型)大于 sizeof(ptr1 的類型),那么在使用指針 ptr1 來訪問 ptr2 所指向的存儲區(qū)時是安全的。如果 sizeof(ptr2 的類型)小于 sizeof(ptr1 的類型),那么在使用指針 ptr1 來訪問 ptr2 所指向的存儲區(qū)時是不安全的。至于為什么,讀者結(jié)合例十七來想一想,應(yīng)該會明白的。

16


更多相關(guān)文檔:

C語言點(diǎn)滴.

表達(dá)式運(yùn)算的順序是由平臺和編譯器決定的,凡是涉及某個值得表達(dá)式,最好可以 自...PICC——C語言的點(diǎn)滴 16頁 1下載券 C語言教程(最全配套免費(fèi)... 533頁 5...

PICC入門筆記

PICC 入門筆記 PIC 單片機(jī) C 語言編程入門筆記 一、 C 語言基礎(chǔ)復(fù)習(xí)---沒 C 語言基礎(chǔ)看起來可能有點(diǎn)困難。C程序的語句 語句名稱 表達(dá)式語句 函數(shù)調(diào)用語句 控制...

PIC單片機(jī)的C語言使用

語言使用( PIC 單片機(jī)的 C 語言使用(一) 在 MPLAB-IDE 中使用 HitechC 編譯...5、節(jié)點(diǎn)文件的工具這時應(yīng)該選擇為“PICC Compiler”(C 編譯器),藍(lán)色圈子里的 ...

第7章 秒表

PICC-C語言實(shí)例PICC-C語言實(shí)例隱藏>> 第7章 秒表 最小巧、最精致、測試最完整、性價比最高的無線射頻開發(fā)平臺和模塊: NORDIC 無線射頻開發(fā)平臺系列 NORDIC 無線射...

更多相關(guān)標(biāo)簽:

c語言點(diǎn)滴 | c語言點(diǎn)滴 趙巖 pdf | c語言點(diǎn)滴 pdf | c語言點(diǎn)滴 百度網(wǎng)盤 | c語言點(diǎn)滴 pdf下載 | C語言點(diǎn)滴pdf百度云 | 英壯英達(dá)都不是好東西 | 腦子是個好東西 |


  本文關(guān)鍵詞:C語言點(diǎn)滴,由筆耕文化傳播整理發(fā)布。



本文編號:247393

資料下載
論文發(fā)表

本文鏈接:http://sikaile.net/wenshubaike/mishujinen/247393.html


Copyright(c)文論論文網(wǎng)All Rights Reserved | 網(wǎng)站地圖 |

版權(quán)申明:資料由用戶c4479***提供,本站僅收錄摘要或目錄,作者需要刪除請E-mail郵箱bigeng88@qq.com