1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        C++指針的應(yīng)用

        共 5436字,需瀏覽 11分鐘

         ·

        2020-12-07 21:35

        C++指針?文章中我們介紹了指針的基本概念和應(yīng)用簡介。我們有提到指針可以使用在鏈表、隊(duì)列和二叉樹,等等。但是這些都會(huì)比較復(fù)查,后面"數(shù)據(jù)結(jié)構(gòu)” 時(shí),我們會(huì)用專門的章節(jié)來講解這些知識(shí)。


        這篇文章,詳細(xì)的探討一下指針和其他關(guān)聯(lián)的具體應(yīng)用。



        1. 指針和數(shù)組的關(guān)系?


        在C語言中,指針與數(shù)組之間的關(guān)系十分密切。實(shí)際上,許多可以用數(shù)組完成的工作都可以使用指針來完成。一般來說,用指針編寫的程序比用數(shù)組編寫的程序執(zhí)行速度快,但另一方面,用指針實(shí)現(xiàn)的程序理解起來稍微困難一些。


        我們先聲明一個(gè)數(shù)組:


        int a[10];// 聲明一個(gè)int類型的數(shù)組,這個(gè)數(shù)組有10個(gè)元素



        我們可以用 a[0]、a[1]、...、a[9] 來表示這個(gè)數(shù)組中的10個(gè)元素,這10個(gè)元素是存儲(chǔ)在一段連續(xù)相鄰的內(nèi)存區(qū)域中的。


        接下來,我們再聲明一個(gè)指針:


        int *p;  // 聲明一個(gè)int類型的指針變量



        p 是一個(gè)指針變量,指向內(nèi)存中的一個(gè)區(qū)域。如果我們對(duì)指針 p 做如下的初始化:


        p = &a[0];  // 對(duì)指針進(jìn)行初始化,p將指向數(shù)組 a 的第 1 個(gè)元素 a[0]



        我們知道,對(duì)指針進(jìn)行自增操作會(huì)讓指針指向與當(dāng)前元素相鄰的下一個(gè)元素,即 *(p + 1) 將指向 a[1] ;同樣的, *(p + i) 將指向 a[i] 。因此,我們可以使用該指針來遍歷數(shù)組 a[10] 的所有元素??梢钥吹?,數(shù)組下標(biāo)與指針運(yùn)算之間的關(guān)系是一一對(duì)應(yīng)的。而根據(jù)定義,數(shù)組類型的變量或表達(dá)式的值是該數(shù)組第 1 個(gè)元素的地址,且數(shù)組名所代表的的就是該數(shù)組第 1 個(gè)元素的地址,故,上述賦值語句可以直接寫成:


        p = a; // a 為數(shù)組名,代表該數(shù)組最開始的一個(gè)元素的地址



        很顯然,一個(gè)通過數(shù)組和下標(biāo)實(shí)現(xiàn)的表達(dá)式可以等價(jià)地通過指針及其偏移量來實(shí)現(xiàn),這就是數(shù)組和指針的互通之處。但有一點(diǎn)要明確的是,數(shù)組和指針并不是完全等價(jià),指針是一個(gè)變量,而數(shù)組名不是變量,它數(shù)組中第 1 個(gè)元素的地址,數(shù)組可以看做是一個(gè)用于保存變量的容器。更直接的方法,我們可以直接看二者的地址,并不一樣:



        #include "stdio.h"                                                                           int main(){    int x[10] = {1,2,3,4,5,6,7,8,9,0};    int *p = x;    printf("x的地址為:%p\n",x);    printf("x[0]的地址為:%p\n",&x[0]);    printf("p的地址為:%p\n",&p);      // 打印指針 p 的地址,并不是指針?biāo)赶虻牡胤降牡刂?/span>    p += 2;    printf("*(p+2)的值為:%d\n",*p);    // 輸出結(jié)果為 3,*(p+2)指向了 x[2]
        return 0;}



        結(jié)果如下:

        可以看到, x 的值與 x[0] 的地址是一樣的,也就是說數(shù)組名即為數(shù)組中第 1 個(gè)元素的地址。實(shí)際上,打印 &x 后發(fā)現(xiàn),x 的地址也是這個(gè)值。而 x 的地址與指針變量 p 的地址是不一樣的。故而數(shù)組和指針并不能完全等價(jià)。


        2. 指針數(shù)組


        指針是一個(gè)變量,而數(shù)組是用于存儲(chǔ)變量的容器,因此,指針也可以像其他變量一樣存儲(chǔ)在數(shù)組中,也就是指針數(shù)組。指針數(shù)組是一個(gè)數(shù)組,數(shù)組中的每一個(gè)元素都是指針。聲明一個(gè)指針數(shù)組的方法如下:



        // 聲明一個(gè)指針數(shù)組,該數(shù)組有10個(gè)元素,其中每個(gè)元素都是一個(gè)指向int類型的指針int?*p[10];


        在上述聲明中,由于 [] 的優(yōu)先級(jí)比 * 高,故 p 先與 [] 結(jié)合,成為一個(gè)數(shù)組 p[];再由 int * 指明這是一個(gè) int 類型的指針數(shù)組,數(shù)組中的元素都是 int 類型的指針。數(shù)組的第 i 個(gè)元素是 *p[i],而 p[i] 是一個(gè)指針。由于指針數(shù)組中存放著多個(gè)指針,操作靈活,在一些需要操作大量數(shù)據(jù)的程序中使用,可以使程序更靈活快速。



        3. 數(shù)組指針


        數(shù)組指針是一個(gè)指針,它指向一個(gè)數(shù)組。聲明一個(gè)數(shù)組指針的方法如下:


        int (*p)[10];        // 聲明一個(gè)數(shù)組指針 p ,該指針指向一個(gè)數(shù)組



        由于 () 的優(yōu)先級(jí)最高,所以 p 是一個(gè)指針,指向一個(gè) int 類型的一維數(shù)組,這個(gè)一維數(shù)組的長度是 10,這也是指針 p 的步長。也就是說,執(zhí)行 p+1 時(shí),p 要跨過 n 個(gè) int 型數(shù)據(jù)的長度。數(shù)組指針與二維數(shù)組聯(lián)系密切,可以用數(shù)組指針來指向一個(gè)二維數(shù)組,如下:


        #include "stdio.h"  int main(){     int arr[2][3] = {1,2,3,4,5,6};               // 定義一個(gè)二維數(shù)組并初始化     int (*p)[3];           // 定義一個(gè)數(shù)組指針,指針指向一個(gè)含有3個(gè)元素的一維數(shù)組      p = arr;            // 將二維數(shù)組的首地址賦給 p,此時(shí) p 指向 arr[0] 或 &arr[0][0]     printf("%d\n",(*p)[0]);              // 輸出結(jié)果為 1     p++;   // 對(duì) p 進(jìn)行算術(shù)運(yùn)算,此時(shí) p 將指向二維數(shù)組的下一行的首地址,即 &arr[1][0]     printf("%d\n",(*p)[1]);                      // 輸出結(jié)果為5      return 0;                                                                                }?



        4. 結(jié)構(gòu)體和指針


        1) 簡單介紹一下結(jié)構(gòu)體

        結(jié)構(gòu)是一個(gè)或多個(gè)變量的集合,這些變量可能為不同的類型,為了處理的方便而將這些變量組織在一個(gè)名字之下。由于結(jié)構(gòu)將一組相關(guān)的變量看做一個(gè)單元而不是各自獨(dú)立的實(shí)體,因此結(jié)構(gòu)有助于組織復(fù)雜的數(shù)據(jù),特別是在大型的程序中。聲明一個(gè)結(jié)構(gòu)的方式如下:


        struct message{            // 聲明一個(gè)結(jié)構(gòu) message    char name[10];             // 成員    int age;    int score;  };
        typedef struct message s_message;     // 類型定義符 typedefs_message mess = {"tongye",23,83};    // 聲明一個(gè) struct message 類型的變量 mess,并對(duì)其進(jìn)行初始化 
        /* 另一種更簡便的聲明方法 */typedef struct{  char name[10];  int age;  int score;}message;



        可以使用?“結(jié)構(gòu)名.成員” 的方式來訪問結(jié)構(gòu)中的成員,如下:


        2) 結(jié)構(gòu)體指針 

        結(jié)構(gòu)指針是指向結(jié)構(gòu)的指針,以上面的結(jié)構(gòu)為例,可以這樣定義一個(gè)結(jié)構(gòu)指針:


        s_message *p;   // 聲明一個(gè)結(jié)構(gòu)指針 p ,該指針指向一個(gè) s_message 類型的結(jié)構(gòu)*p = &mess;  // 對(duì)結(jié)構(gòu)指針的初始化與普通指針一樣,也是使用取地址符 &




        C語言中使用?“->” 操作符來訪問結(jié)構(gòu)指針的成員,舉個(gè)例子:


        #include "stdio.h"
        typedef struct{ char name[10]; int age; int score; }message;int main(){ message mess = {"tongye",23,83}; message *p = &mess;
        printf("%s\n",p->name);      // 輸出結(jié)果為:tongye printf("%d\n",p->score); // 輸出結(jié)果為:83
        return 0;}?



        5. 指針和函數(shù)的關(guān)系


        C語言的所有參數(shù)均是以“傳值調(diào)用”的方式進(jìn)行傳遞的,這意味著函數(shù)將獲得參數(shù)值的一份拷貝。這樣,函數(shù)可以放心修改這個(gè)拷貝值,而不必?fù)?dān)心會(huì)修改調(diào)用程序?qū)嶋H傳遞給它的參數(shù)。?


        1) 指針作為函數(shù)的參數(shù)

        傳值調(diào)用的好處是是被調(diào)函數(shù)不會(huì)改變調(diào)用函數(shù)傳過來的值,可以放心修改。但是有時(shí)候需要被調(diào)函數(shù)回傳一個(gè)值給調(diào)用函數(shù),這樣的話,傳值調(diào)用就無法做到。為了解決這個(gè)問題,可以使用傳指針調(diào)用。指針參數(shù)使得被調(diào)函數(shù)能夠訪問和修改主調(diào)函數(shù)中對(duì)象的值。用一個(gè)例子來說明:


        #include "stdio.h"// 參數(shù)為普通的 int 變量void swap1(int a,int b)        {  int temp;  temp = a;  a = b;  b = temp;}// 參數(shù)為指針,接受調(diào)用函數(shù)傳遞過來的變量地址作為參數(shù),對(duì)所指地址處的內(nèi)容進(jìn)行操作// 最終結(jié)果是,地址本身并沒有改變,但是這一地址所對(duì)應(yīng)的內(nèi)存段中的內(nèi)容發(fā)生了變化,即x,y的值發(fā)生了變化void swap2(int *a,int *b)      {  int temp;                      temp = *a;  *a = *b;  *b = temp;}int main(){  int x = 1,y = 2;  swap1(x,y);                     // 將 x,y 的值本身作為參數(shù)傳遞給了被調(diào)函數(shù)  printf("%d %5d\n",x,y);         // 輸出結(jié)果為:1     2  swap(&x,&y);                     // 將 x,y 的地址作為參數(shù)傳遞給了被調(diào)函數(shù)  printf("%d %5d\n",x,y);         // 輸出結(jié)果為:2     1  return 0;}



        2) 指向函數(shù)的指針

        在C語言中,函數(shù)本身不是變量,但是可以定義指向函數(shù)的指針,也稱作函數(shù)指針,函數(shù)指針指向函數(shù)的入口地址。這種類型的指針可以被賦值、存放在數(shù)組中、傳遞給函數(shù)以及作為函數(shù)的返回值等等。聲明一個(gè)函數(shù)指針的方法如下:

        返回值類型 (* 指針變量名)([形參列表]);


        int (*pointer)(int *,int *);        // 聲明一個(gè)函數(shù)指針



        上述代碼聲明了一個(gè)函數(shù)指針 pointer ,該指針指向一個(gè)函數(shù),函數(shù)具有兩個(gè) int * 類型的參數(shù),且返回值類型為 int。下面的代碼演示了函數(shù)指針的用法:



        #include "stdio.h"#include "string.h"
        // 聲明一個(gè)函數(shù) str_comp,該函數(shù)有兩個(gè) const char 類型的指針,函數(shù)的返回值為 int 類型int str_comp(const char *m,const char *n);
        // 聲明一個(gè)函數(shù) comp ,注意該函數(shù)的第三個(gè)參數(shù),是一個(gè)函數(shù)指針 void comp(char *a,char *b,int (*prr)(const char *,const char*));
        int main(){ char str1[20]; // 聲明一個(gè)字符數(shù)組 char str2[20];// 聲明并初始化一個(gè)函數(shù)指針,且返回值為 int 類型 int (*p)(const char *,const char *) = str_comp;            gets(str1); // 使用 gets() 函數(shù)從 I/O 讀取一行字符串 gets(str2); comp(str1,str2,p); // 函數(shù)指針 p 作為參數(shù)傳給 comp 函數(shù)
        return 0;}
        int str_comp(const char *m,const char *n){   // 庫函數(shù) strcmp 用于比較兩個(gè)字符串 if(strcmp(m,n) == 0) return 0; else return 1;}
        /* 函數(shù) comp 接受一個(gè)函數(shù)指針作為它的第三個(gè)參數(shù) */void comp(char *a,char *b,int (*prr)(const char *,const char*)){ if((*prr)(a,b) == 0) printf("str1 = str2\n"); else printf("str1 != str2\n");}



        推薦閱讀:
        專輯|Linux文章匯總
        專輯|程序人生
        專輯|C語言
        我的知識(shí)小密圈



        嵌入式Linux
        微信掃描二維碼,關(guān)注我的公眾號(hào)?
        瀏覽 71
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            亚洲无码一区在线 | 美女洗澡18隐私免费 | 巨乳伦理片 | 日韩深夜视频 | 亚洲AV成人无码久久精品麻豆 | 欧美精品特一级黑妇黄色影院 | 成人肏屄 | 爆乳肥臀一区二区无码视频网站 | 巨大胸大乳美女在办公室 | 俺也去俺来也www色官网 |