新聞中心

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

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

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

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

  首先讓我們來看看定義一個指針的一般形式為:

  基類型 *指針變量名

  看了上面的指針的定義形式,我們可能對于有些地方會有疑惑,如為什么要指定基類型呢?因為我們都知道整型和字符型在內(nèi)存中占的字節(jié)數(shù)是不相同的,當我們進行指針的移動和指針的運算時,如果指針指向的是一個整型變量,那么指針移動一個位置就是移動4個字節(jié),但是如果指針指向的是一個字符型的變量,那么指針移動的就是一個字節(jié),因此我們必須規(guī)定指針變量所指向的基類型。

  為了不枯燥的講解我們來看看下面的代碼吧。(注意:本博客的所有代碼均使用vc6編譯運行,所以可能有的規(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);

  }

  運行結(jié)果如下:

  

 

  在此我們定義了兩個整型指針int *pointer_1,*pointer_2;,它們分別指向變量a和b,值得注意的是*pointer_1和a、*pointer_2和b是共用同一個存儲空間的,當我們在接下類的代碼中改變 *pointer_1=300;時,由輸出就可以看出來a的值也跟隨發(fā)生了改變。但是當我們聲明了一個 int c=500;之后,使用pointer_2=&c;,b的值不變,僅僅是改變*pointer_2,因為我僅僅是改變了*pointer_2指向了c的存儲空間,如果有有興趣的讀者可以自己驗證下如果我們修改了a的值之后*pointer_1的值會跟隨一起改變,因為他們指向的是同一個存儲空間。

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

  #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);

  }

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

  

 

  結(jié)果跟我們想象的不一樣,a、b沒有實現(xiàn)交換的原因是因為我們使用的是傳值,而不是傳址,所以調(diào)用的過程中做的處理就是把a、b的值復(fù)制到另外申請的兩個空間p1、p2中去,因而交換操作是在p1、p2的空間中進行的,所以對于a、b的值并沒有影響。c、d的初值為什么沒有跟a、b的值一樣呢,因為我們在初始化的過程中給c、d賦初值的時候a、b的并沒有給定初值,所以a、b的初值是在編譯的過程中由系統(tǒng)給定的,又因為我們申請的c、d的空間是跟a、b沒有任何關(guān)系的,所以接下來再對a、b賦初值的時候c、d的初值并不會改變。

  下一個代碼:

  #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;

  }

  看看上面這個代碼似乎滿足了我們前面說的傳址的要求,那先讓我們來看看實驗結(jié)果吧。

  

 

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

 

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

  下一個代碼:

  #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)了一個我們想要的結(jié)果了。從以上的分析讀者自己也知道原因所在了吧,這里操作的才是p1、p2所指向的地址,才真正的做到了對于a、b存儲空間的數(shù)值的交換。細心的讀者可能看到了我們在代碼中用了紅色部分標記的代碼,它完全可以用一句int temp;來替代,之所以我們在這里要用int *temp;無非是要大家牢記對于指針一些特殊的使用,如果我們沒有這句temp=(int *)malloc(sizeof(int));,以上代碼在編譯的過程中是不會有任何錯誤的,但是在運行的過程中就會出現(xiàn)錯誤,所以通常情況下我們在使用指針的過程中,要特別注意野指針情況的出現(xiàn),以免出現(xiàn)一些莫名奇妙的有錯。

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




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

評論


相關(guān)推薦

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

關(guān)閉