新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 牛人業(yè)話 > C語(yǔ)言的那些小秘密之指針(一)

        C語(yǔ)言的那些小秘密之指針(一)

        作者: 時(shí)間:2015-03-23 來(lái)源:網(wǎng)絡(luò) 收藏

          懂得的人都知道,之所以強(qiáng)大,以及其自由性,絕大部分體現(xiàn)在其靈活的運(yùn)用上。因此,說(shuō)是c語(yǔ)言的靈魂,一點(diǎn)都不為過(guò)。所以從我的標(biāo)題加了個(gè)(一)也可以看出的重要性,我盡可能的向大家交代清楚我對(duì)于指針的理解。所以在講解的過(guò)程中我盡可能的用代碼加文字的描述方式,通過(guò)代碼的分析來(lái)加深我們對(duì)于指針的理解,我給出的都是完整的代碼,所以讀者可以在看的過(guò)程中直接copy下去即可運(yùn)行,希望下面的講解能夠?qū)δ阌兴鶐椭?/p>本文引用地址:http://www.104case.com/article/271428.htm

          首先讓我們來(lái)看看定義一個(gè)指針的一般形式為:

          基類型 *指針變量名

          看了上面的指針的定義形式,我們可能對(duì)于有些地方會(huì)有疑惑,如為什么要指定基類型呢?因?yàn)槲覀兌贾勒秃妥址驮趦?nèi)存中占的字節(jié)數(shù)是不相同的,當(dāng)我們進(jìn)行指針的移動(dòng)和指針的運(yùn)算時(shí),如果指針指向的是一個(gè)整型變量,那么指針移動(dòng)一個(gè)位置就是移動(dòng)4個(gè)字節(jié),但是如果指針指向的是一個(gè)字符型的變量,那么指針移動(dòng)的就是一個(gè)字節(jié),因此我們必須規(guī)定指針變量所指向的基類型。

          為了不枯燥的講解我們來(lái)看看下面的代碼吧。(注意:本博客的所有代碼均使用vc6編譯運(yùn)行,所以可能有的規(guī)則跟的稍有區(qū)別)

          #include

          int main()

          {

          int a,b;

          int *pointer_1,*pointer_2;

          a=100;

          b=200;

          pointer_1=&a;

          pointer_2=&b;

          printf("--------------------變換前-------------------n");

          printf("a=%dtb=%dn",a,b);

          printf("*pointer_1=%dt*pointer_2=%dn",*pointer_1,*pointer_2);

          *pointer_1=300;

          int c=500;

          pointer_2=&c;

          printf("--------------------變換后-------------------n");

          printf("a=%dt*pointer_1=%dn",a,*pointer_1);

          printf("c=%dtb=%dt*pointer_2=%dn",c,b,*pointer_2);

          }

          運(yùn)行結(jié)果如下:

          

         

          在此我們定義了兩個(gè)整型指針int *pointer_1,*pointer_2;,它們分別指向變量a和b,值得注意的是*pointer_1和a、*pointer_2和b是共用同一個(gè)存儲(chǔ)空間的,當(dāng)我們?cè)诮酉骂惖拇a中改變 *pointer_1=300;時(shí),由輸出就可以看出來(lái)a的值也跟隨發(fā)生了改變。但是當(dāng)我們聲明了一個(gè) int c=500;之后,使用pointer_2=&c;,b的值不變,僅僅是改變*pointer_2,因?yàn)槲覂H僅是改變了*pointer_2指向了c的存儲(chǔ)空間,如果有有興趣的讀者可以自己驗(yàn)證下如果我們修改了a的值之后*pointer_1的值會(huì)跟隨一起改變,因?yàn)樗麄冎赶虻氖峭粋€(gè)存儲(chǔ)空間。

          接下來(lái)看看如何在函數(shù)的參數(shù)中來(lái)使用指針。

          #include

          swap(int p1,int p2)

          {

          int temp;

          temp=p1;

          p1=p2;

          p2=temp;

          }

          int main()

          {

          int a,b;

          int *pointer_1,*pointer_2;

          int c,d;

          c=a;

          d=b;

          pointer_1=&a;

          pointer_2=&b;

          a=20;

          b=30;

          swap(a,b);

          printf("a=%dtb=%dn",a,b);

          printf("a=%dtb=%dn",*pointer_1,*pointer_2);

          printf("c=%dtd=%dn",c,d);

          }

          初步分析上面的代碼,看似是要通過(guò)一個(gè)函數(shù)的調(diào)用來(lái)實(shí)現(xiàn)一個(gè)a、b的交換,還有就是通過(guò)c=a;、 d=b;來(lái)實(shí)現(xiàn)對(duì)c、d賦初值。先來(lái)看看下面的運(yùn)行結(jié)果:

          

         

          結(jié)果跟我們想象的不一樣,a、b沒有實(shí)現(xiàn)交換的原因是因?yàn)槲覀兪褂玫氖莻髦?,而不是傳址,所以調(diào)用的過(guò)程中做的處理就是把a(bǔ)、b的值復(fù)制到另外申請(qǐng)的兩個(gè)空間p1、p2中去,因而交換操作是在p1、p2的空間中進(jìn)行的,所以對(duì)于a、b的值并沒有影響。c、d的初值為什么沒有跟a、b的值一樣呢,因?yàn)槲覀冊(cè)诔跏蓟倪^(guò)程中給c、d賦初值的時(shí)候a、b的并沒有給定初值,所以a、b的初值是在編譯的過(guò)程中由系統(tǒng)給定的,又因?yàn)槲覀兩暾?qǐng)的c、d的空間是跟a、b沒有任何關(guān)系的,所以接下來(lái)再對(duì)a、b賦初值的時(shí)候c、d的初值并不會(huì)改變。

          下一個(gè)代碼:

          #include

          swap(int *p1,int *p2)

          {

          int *temp;

          temp=p1;

          p1=p2;

          p2=temp;

          }

          int main()

          {

          int a,b;

          int *pointer_1,*pointer_2;

          int c,d;

          c=a;

          d=b;

          pointer_1=&a;

          pointer_2=&b;

          a=20;

          b=30;

          printf("********************調(diào)用前******************n");

          printf("a=%dtb=%dn",a,b);

          swap(pointer_1,pointer_2);

          printf("********************調(diào)用后******************n");

          printf("a=%dtb=%dn",a,b);

          printf("*pointer_1=%dt*pointer_2=%dn",*pointer_1,*pointer_2);

          printf("c=%dtd=%dn",c,d);

          return 0;

          }

          看看上面這個(gè)代碼似乎滿足了我們前面說(shuō)的傳址的要求,那先讓我們來(lái)看看實(shí)驗(yàn)結(jié)果吧。

          

         

          結(jié)果似乎也是出乎我們的意料之外,為什么使用了傳值卻還是沒有能夠?qū)崿F(xiàn)呢?如果我們?cè)谡{(diào)用函數(shù)中加上一句 printf("*p1=%dt*p2=%dn",*p1,*p2);,得到下面的結(jié)果:

         

          從結(jié)果來(lái)看似乎告訴我們,我們已經(jīng)實(shí)現(xiàn)交換了,但是為什么沒有能夠返回來(lái)呢?在這里要注意了,因?yàn)槲覀冊(cè)诤瘮?shù)的交換語(yǔ)句僅僅是改變了局部指針變量p1和p2的值,所以沒有改變a、b的值,所以使用printf("*p1=%dt*p2=%dn",*p1,*p2);使得我們的確看到了a、b交換的假象,僅僅是改變了局部變量p1和p2的值。

          下一個(gè)代碼:

          #include

          #include

          swap(int *p1,int *p2)

          {

          int *temp;

          temp=(int *)malloc(sizeof(int));

          *temp=*p1;

          *p1=*p2;

          *p2=*temp;

          free(temp);

          }

          int main()

          {

          int a,b;

          int *pointer_1,*pointer_2;

          int c,d;

          c=a;

          d=b;

          pointer_1=&a;

          pointer_2=&b;

          a=20;

          b=30;

          printf("********************調(diào)用前******************n");

          printf("a=%dtb=%dn",a,b);

          swap(pointer_1,pointer_2);

          printf("********************調(diào)用后******************n");

          printf("a=%dtb=%dn",a,b);

          printf("*pointer_1=%dt*pointer_2=%dn",*pointer_1,*pointer_2);

          printf("c=%dtd=%dn",c,d);

          return 0;

          }

          看看也行結(jié)果:

          

         

          最后終于出現(xiàn)了一個(gè)我們想要的結(jié)果了。從以上的分析讀者自己也知道原因所在了吧,這里操作的才是p1、p2所指向的地址,才真正的做到了對(duì)于a、b存儲(chǔ)空間的數(shù)值的交換。細(xì)心的讀者可能看到了我們?cè)诖a中用了紅色部分標(biāo)記的代碼,它完全可以用一句int temp;來(lái)替代,之所以我們?cè)谶@里要用int *temp;無(wú)非是要大家牢記對(duì)于指針一些特殊的使用,如果我們沒有這句temp=(int *)malloc(sizeof(int));,以上代碼在編譯的過(guò)程中是不會(huì)有任何錯(cuò)誤的,但是在運(yùn)行的過(guò)程中就會(huì)出現(xiàn)錯(cuò)誤,所以通常情況下我們?cè)谑褂弥羔樀倪^(guò)程中,要特別注意野指針情況的出現(xiàn),以免出現(xiàn)一些莫名奇妙的有錯(cuò)。

        c語(yǔ)言相關(guān)文章:c語(yǔ)言教程




        關(guān)鍵詞: C語(yǔ)言 指針

        評(píng)論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 巩留县| 马龙县| 安丘市| 阿拉善盟| 红原县| 霍山县| 建水县| 滨海县| 新田县| 柯坪县| 塔城市| 靖州| 彭水| 博湖县| 日土县| 镇康县| 淳化县| 安多县| 三原县| 金阳县| 汉寿县| 保靖县| 江阴市| 秭归县| 郓城县| 汉沽区| 南江县| 保德县| 三台县| 新巴尔虎右旗| 墨脱县| 嘉善县| 横山县| 嘉兴市| 松滋市| 梁平县| 香河县| 阳谷县| 林州市| 舞阳县| 西昌市|