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

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

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

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



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

適用條件:在 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ù)這些中間臨時(shí)變量就需要大量的開銷,嚴(yán)重影響中斷服務(wù)的效 率。其實(shí),在 picc 中,對(duì)中斷中使用的臨時(shí)變量,為了防止重入或覆蓋,干脆就是中斷專用 在我們的 中斷專用。 中斷專用 picc 編程中,臨時(shí)變量(或者說局部變量),都有其生存期,在生存期結(jié)束后,可被覆蓋。 但中斷函數(shù)中使用到的臨時(shí)變量卻與一般概念上的臨時(shí)變量有很大的區(qū)別。中斷函數(shù)中使用到的臨時(shí) 變量和中斷函數(shù)中不使用到的臨時(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-----三個(gè)全局變量 s1[40]----40 個(gè)中斷調(diào)用使用的臨時(shí)變量 s2[50]----50 個(gè)中斷中使用的臨時(shí)變量 保護(hù) w、status 和 pclath 用去三個(gè)內(nèi)存變量

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

再看一下下面的例子: #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-----三個(gè)全局變量 s1[20]----20 個(gè)中斷調(diào)用使用的臨時(shí)變量 s2[50]----50 個(gè)中斷中使用的臨時(shí)變量 s3[20]----20 個(gè)非中斷使用的臨時(shí)變量 保護(hù) w、status 和 pclath 用去三個(gè)內(nèi)存變量
2

從上面的例子中也可以看出,中斷使用的臨時(shí)變量和中斷外使用的臨時(shí)變量不可重疊。 eyuge2 兄所說的 picc 自動(dòng)保護(hù)現(xiàn)場(chǎng),其實(shí)就是 picc 對(duì)中斷中使用的臨時(shí)變量實(shí)施“禁入”。也就是, 中斷內(nèi)可實(shí)施中斷內(nèi)臨時(shí)變量覆蓋;中斷外的臨時(shí)變量也可進(jìn)行覆蓋;但中斷內(nèi)外之間的臨時(shí)變量不可相 互覆蓋。 當(dāng)然為了防止重入,中斷中使用的函數(shù)不可在中斷外被調(diào)用。(picc 可自動(dòng)實(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)場(chǎng)保護(hù),編譯后結(jié)果是直接返回。 0004 0009 retfie

第二次, 中斷處理函數(shù)增加一條對(duì)全局變量的操作。 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,不對(duì)全局變量進(jìn)行現(xiàn)場(chǎng)保護(hù)。

最后來看一個(gè)中斷處理函數(shù)中調(diào)用一個(gè)函數(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

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

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

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

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

返回一個(gè)整型值,實(shí)際上也相當(dāng)于返回一個(gè)指針變量的值,不過這時(shí)的變量是函數(shù)本身而已,而整個(gè)函 數(shù)相當(dāng)于一個(gè)“變量”。例如下面一個(gè)返回指針函數(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í),每一個(gè)函數(shù)都有一個(gè)入口地址,該入口地址就是函數(shù)指針?biāo)赶虻牡刂。有了指向函?shù)的指針變量 后,可用該指針變量調(diào)用函數(shù),就如同用指針變量可引用其他類型變量一樣,在這些概念上一致的。函數(shù) 指針有兩個(gè)用途:調(diào)用函數(shù)和做函數(shù)的參數(shù)。函數(shù)指針的說明方法為: 數(shù)據(jù)類型標(biāo)志符 (*指針變量名)(參數(shù));注:函數(shù)括號(hào)中的參數(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)合與指針 先看下面的一個(gè)簡(jiǎn)單的舉例 typedef struct datas { char datah; char datal; struct datas *next; } data; //a 是一個(gè)結(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 是一個(gè)結(jié)構(gòu)型變量,ptr 則是指向結(jié)構(gòu)型變量的指針,在 c 語(yǔ)言里,通過形如 ptr->x 的形式來 訪問結(jié)構(gòu)或者指針的成員。在結(jié)構(gòu)變量中定義了一個(gè)指針 struct datas *next; 這是在指針鏈中常用到 的,ptr1->next=ptr2; ptr2->next=0;實(shí)際上已經(jīng)建立了一條簡(jiǎn)單的指針鏈,當(dāng)然建立指針鏈用這種初始 化的方法不夠簡(jiǎn)單,但是上面的程序只是為了說明指針和結(jié)構(gòu)而已。
8

在單片機(jī)的 c 語(yǔ)言程序中,聯(lián)合和結(jié)構(gòu)是經(jīng)常用在一起的下面在舉一個(gè)簡(jiǎn)單的列子: 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,道理和第一個(gè)列子一樣,只是應(yīng)該注意的是在 piccdata 型 變量中占用的空間為 2 個(gè)字節(jié)而不是 4 個(gè)字節(jié)。! 另:結(jié)構(gòu)與聯(lián)合是 pic 應(yīng)用的一個(gè)好東西,這點(diǎn) hotpower 曾經(jīng)有一很經(jīng)典的文章,在此列中,只要稍微 加以改動(dòng),就可以對(duì)一個(gè) 16 位變量即可以整體訪問,也可分為高八位訪問和低八位訪問。這在 ad 轉(zhuǎn)換中 是很有用的。 4: const 與指針 如果 const 關(guān)鍵字不涉及到指針,我

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

const int a[8]={1,2,3,-3,3,5,6,7}; const int *ptr; main() { ptr=a; ptr++; } 顯然 ptr 是一個(gè)指向常量的指針,ptr 指向的數(shù)是不可變的,,但是 ptr 本身是可變的,我們可以通過 ptr 來訪問定義在 rom 中的數(shù)組 a[8]; 歡迎補(bǔ)充和指正,謝謝! 讀寫片內(nèi) eeprom 數(shù)據(jù)區(qū),每一本相關(guān)的數(shù)據(jù)手冊(cè)都有詳細(xì)的例程,抄上去就可以了。如果連抄上也不行, 那你還有什么是可以的呢? 什么都想要現(xiàn)成的,自己一點(diǎn)主觀的進(jìn)取心都沒有。你要用 c 寫程序,這當(dāng)然是好事,可是連現(xiàn)成的匯編 語(yǔ)句都無法用 c 語(yǔ)言復(fù)述一遍,那你還能用 c 寫出什么有用的代碼? 自己如果不清楚,就不要瞎說。什么“不是將 wr 置 1,寫完后會(huì)自動(dòng)將 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 語(yǔ)言指針的奧秘 指針的概念 例三:

intarray[20]; int*ptr=array; ... //此處略去為整型數(shù)組賦值的代碼。 ... for(i=0;ia; ptr->b; ptr->c;

又請(qǐng)問怎樣通過指針 pstr 來訪問 ss 的三個(gè)成員變量? 答案: *pstr;//訪問了 ss 的成員 a。 *(pstr+1);//訪問了 ss 的成員 b。 *(pstr+2)//訪問了 ss 的成員 c。 雖然我在我的 MSVC++6.0 上調(diào)式過上述代碼,但是要知道,這樣使用 pstr 來訪問結(jié)構(gòu)成員是不正規(guī)的,為了說明為什么不正規(guī),讓我們看看怎樣通過指針來訪問數(shù)組的各個(gè)單元: 例十二:

intarray[3]={35,56,37}; int*pa=array; 通過指針 pa 訪問數(shù)組 array 的三個(gè)單元的方法是: *pa;//訪問了第 0 號(hào)單元 *(pa+1);//訪問了第 1 號(hào)單元 *(pa+2);//訪問了第 2 號(hào)單元 從格式上看倒是與通過指針訪問結(jié)構(gòu)成員的不正規(guī)方法的格式一樣。 所有的 C/C++編譯器在排列數(shù)組的單元時(shí),總是把各個(gè)數(shù)組單元存放在連續(xù)的存儲(chǔ)區(qū)里,單元和單元之間沒有空隙。但在存放結(jié)構(gòu)對(duì)象的各個(gè)成員時(shí),在某種編譯環(huán)境下,可能會(huì) 需要字對(duì)齊或雙字對(duì)齊或者是別的什么對(duì)齊,需要在相鄰兩個(gè)成員之間加若干個(gè)"填充字節(jié)",這就導(dǎo)致各個(gè)成員之間可能會(huì)有若干個(gè)字節(jié)的空隙。

所以,在例十二中,即使*pstr 訪問到了結(jié)構(gòu)對(duì)象 ss 的第一個(gè)成員變量 a,也不能保證*(pstr+1)就一定能訪問到結(jié)構(gòu)成員 b。因?yàn)槌蓡T a 和成員 b 之間可能會(huì)有若干填充字節(jié),說不 定*(pstr+1)就正好訪問到了這些填充字節(jié)呢。這也證明了指針的靈活性。要是你的目的就是想看看各個(gè)結(jié)構(gòu)成員之間到底有沒有填充字節(jié),嘿,這倒是個(gè)不錯(cuò)的方法。 通過指針訪問結(jié)構(gòu)成員的正確方法應(yīng)該是象例十二中使用指針 ptr 的方法。 指針和函數(shù)的關(guān)系 可以把一個(gè)指針聲明成為一個(gè)指向函數(shù)的指針。

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

13

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

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

14

一個(gè)函數(shù)如果使用了指針作為形參,那么在函數(shù)調(diào)用語(yǔ)句的實(shí)參和形參的結(jié)合過程中,也會(huì)發(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; } } 注意這是一個(gè) 32 位程序,故 int 類型占了四個(gè)字節(jié),char 類型占一個(gè)字節(jié)。函數(shù) fun 的作用是把一個(gè)整數(shù)的四個(gè)字節(jié)的順序來個(gè)顛倒。注意到了嗎?在函數(shù)調(diào)用語(yǔ)句中,實(shí)參&a 的結(jié)果是一個(gè)指針,它的類型是 int*,它指向的類型是 int。形參這個(gè)指針的類型是 char*,它指向的類型是 char。這樣,在實(shí)參和形參的結(jié)合過程中,我們必須進(jìn)行一次從 int*類型到 c har*類型的轉(zhuǎn)換。結(jié)合這個(gè)例子,我們可以這樣來想象編譯器進(jìn)行轉(zhuǎn)換的過程:編譯器先構(gòu)造一個(gè)臨時(shí)指針 char*temp, 然后執(zhí)行 temp=(char*)&a,最后再把 temp 的值傳遞給 s。所 以最后的結(jié)果是:s 的類型是 char*,它指向的類型是 char,它指向的地址就是 a 的首地址。 我們已經(jīng)知道,指針的值就是指針指向的地址,在 32 位程序中,指針的值其實(shí)是一個(gè) 32 位整數(shù)。那可不可以把一個(gè)整數(shù)當(dāng)作指針的值直接賦給指針呢?就象下面的語(yǔ)句: 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)后面兩條語(yǔ)句全是錯(cuò)的。那么我們的目的就不能達(dá)到了嗎?不,還有辦法:

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

15

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

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

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

16


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

C語(yǔ)言點(diǎn)滴.

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

PICC入門筆記

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

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

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

第7章 秒表

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

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

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


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



本文編號(hào):247393

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

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


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

版權(quán)申明:資料由用戶c4479***提供,本站僅收錄摘要或目錄,作者需要?jiǎng)h除請(qǐng)E-mail郵箱bigeng88@qq.com
国产精品丝袜美腿一区二区| 五月婷婷六月丁香在线观看| 美女被后入福利在线观看| 国产一级特黄在线观看| 加勒比日本欧美在线观看| 大尺度激情福利视频在线观看| 婷婷色网视频在线播放| 91国内视频一区二区三区| 欧美三级不卡在线观线看| 国产一区欧美午夜福利| 国产又粗又猛又爽又黄的文字| 插进她的身体里在线观看骚| 国产三级视频不卡在线观看| 婷婷色网视频在线播放| 日韩国产亚洲欧美激情| 日本在线视频播放91| 国产精品一区欧美二区| 国产麻豆精品福利在线| 欧美久久一区二区精品| 在线观看视频国产你懂的| 亚洲天堂一区在线播放| 婷婷激情四射在线观看视频 | 国产精品内射婷婷一级二级| 欧美日本精品视频在线观看| 国产又粗又长又大的视频| 熟女中文字幕一区二区三区| 日韩精品亚洲精品国产精品| 天海翼精品久久中文字幕| 国产成人亚洲精品青草天美| 日韩在线视频精品中文字幕| 91麻豆视频国产一区二区| 日韩三极片在线免费播放| 欧美日韩久久精品一区二区| 精品精品国产欧美在线| 免费观看成人免费视频| 成人日韩视频中文字幕| 97人妻精品一区二区三区男同| 亚洲男人的天堂久久a| 亚洲少妇人妻一区二区| 日韩一级一片内射视频4k| 国产精品一区二区三区激情|