C語言 指針數組 多維數組

.

作者 : 萬境絕塵

轉載請註明出處 :http://blog.csdn.net/shulianghan/article/details/21402047

.

1. 地址算數運算示例

指針算數運算 : int *p, array[5]; p = array; p 指向一個 int 數組元素, p + i 的地址時數組中第 i 個元素的地址, 即 p + i 指向 第 i 個元素;

存儲分配示例函數 :

-- char *alloc(int n) 函數 : 傳入分配的字元個數, 返回連續字元存儲單元指針, 這個指針可以存儲 n 個字元元素;

-- int afree(char *p) 函數 : 釋放分配的內存空間;

-- 缺陷 : 分配內存的時候, 有一個偏移量, 偏移量的大小代表已經分配了多少內存, 釋放內存必須按照分配內存的順序釋放, 否則偏移量就會亂;

-- 內存分配原理 : 設置一個大數組, 內存分配就分配這個數組的中的空間, alloc 和 afree 函數操作的是指針, 不是數組, 因此這個數組可以隱藏, 將數組定義為static 類型, 那麼在其它文件中, 不能訪問該數組, 設置一個偏移量, 當分配 n 個元素, 偏移量就加上 n, 當偏移量 等於 數組大小, 說明內存全部分配完畢;

-- 偏移量設計 : 設置一個偏移量, 偏移量始終指向大數組的下一個空閑的元素地址, 當分配內存的時候, 通過計算 數組首地址 + 數組長度 - 偏移量 >= 分配大小 , 成立的話就可以分配內存, 分配內存就是將偏移量 加上 分配大小; 釋放內存的時候, 就將偏移量 指向 釋放內存的指針的首地址, 因此 要保持後進先出的次序;

代碼 :

[cpp] view plaincopy

  1. /*************************************************************************
  2. >FileName:alloc_afree.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:2014年03月17日星期一19時34分08秒
  6. ************************************************************************/
  7. #include<stdio.h>
  8. //用於內存分配載體的大數組大小
  9. #defineALLOCSIZE1000
  10. /*
  11. *該數組就是用於內存分配的主體,
  12. *設置為static,意味著只能在本文件中訪問,在其它文件中不能訪問
  13. */
  14. staticcharalloc_buf[ALLOCSIZE];
  15. /*
  16. *將alloc_buf數組的首地址賦值給allocp字元指針
  17. *對allocp進行算數運算,每次加減都是char*運算數
  18. *allocp的值就可以代表所分配內存的首地址
  19. */
  20. staticchar*allocp=alloc_buf;
  21. /*
  22. *分配n個char類型數組的內存,
  23. *如果分配成功,返回分配的內存的指針,
  24. *如果分配失敗,返回0
  25. */
  26. char*alloc(intn)
  27. {
  28. //如果大數組剩餘的空間可以分配,那麼就進行分配
  29. if(alloc_buf+ALLOCSIZE-allocp>=n)
  30. {
  31. //分配空間,allocp指向下一個空間的內存首地址
  32. allocp+=n;
  33. //返回分配的空間首地址
  34. returnallocp-n;
  35. }else//如果數組剩餘空間不足,返回0
  36. {
  37. return0;
  38. }
  39. }
  40. /*
  41. *釋放分配的內存
  42. *釋放內存就是將allocp指針地址指向要釋放的內存指針首地址
  43. */
  44. voidafree(char*p)
  45. {
  46. //釋放內存的前提是內存必須是大於數組首地址,小於數組尾地址
  47. if(p>=alloc_buf&&p<alloc_buf+ALLOCSIZE)
  48. {
  49. allocp=p;
  50. printf("allocp=%p
    ",allocp);
  51. }
  52. }
  53. intmain(intargc,char**argv)
  54. {
  55. char*p1;
  56. char*p2;
  57. char*p3;
  58. char*p4;
  59. //列印數組首地址
  60. printf("alloc_buf=%p
    ",alloc_buf);
  61. //分配300個字元內存
  62. p1=alloc(300);
  63. printf("char*p1=alloc(300),p1=%p
    ",p1);
  64. p2=alloc(300);
  65. printf("char*p2=alloc(300),p2=%p
    ",p2);
  66. p3=alloc(300);
  67. printf("char*p3=alloc(300),p3=%p
    ",p3);
  68. //上面已經分配了900了,在分配就溢出了,這裡alloc()函數返回0
  69. p4=alloc(300);
  70. printf("char*p4=alloc(300),p4=%p
    ",p4);
  71. afree(p4);
  72. afree(p3);
  73. afree(p2);
  74. afree(p1);
  75. }

執行結果 :[cpp] view plaincopy

  1. octopus@octopus-Vostro-270s:~/code/c/pointer$gccalloc_afree.c
  2. octopus@octopus-Vostro-270s:~/code/c/pointer$./a.out
  3. alloc_buf=0x804a060
  4. char*p1=alloc(300),p1=0x804a060
  5. char*p2=alloc(300),p2=0x804a18c
  6. char*p3=alloc(300),p3=0x804a2b8
  7. char*p4=alloc(300),p4=(nil)
  8. allocp=0x804a2b8
  9. allocp=0x804a18c
  10. allocp=0x804a060

函數執行示例圖 :

-- alloc()函數示例圖 :

-- afree()函數示例圖 :

指針初始化 : static char *allocp = alloc_buf, 將char數組的首地址賦值給char類型指針;

-- 初始化內容 : 0 或者 地址;

-- 地址限定 : 對指針初始化的地址, 該地址存儲的數據的類型必須是該指針類型;

內存可用判斷 : alloc_buf + ALLOCSIZE - allocp >= n;

-- 意義 : alloc_buf 是數組首地址, ALLOCSIZE 是數組大小, allocp是可用內存偏移量, alloc_buf + ALLOCSIZE -allocp 結果是可用的內存量, 如果可用內存大於n, 則可以賦值;

-- 如果內存不足 : 內存不足, 將0作為地址返回, C語言中設定 0 不是有效的數據地址, 0地址的數據為NULL, 返回0表示發生了異常事件;

指針整數轉換特例 : 指針 和 整數 不能相互轉換;

-- 通常情況 : 指針 和 整型 之間不能相互轉換, 0 除外;

-- 特例 : 常量 0 可以賦值給指針, 指針 可以和 常量 0 進行比較, 這裡注意是常量;

-- 0的特殊性 : NULL 可以代替 常量0, 常量0 是一個特殊值;

指針運算 :

-- 比較運算 : 兩個指針都指向同一個數組中的元素, 那麼兩個指針之間的比較是有意義的, 指向兩個不同數組元素的指針之間比較無意義;

-- 加減運算 : 指向數組元素的指針, 進行加減運算, 地址的計算按照 運算數 * 指針指向元素的大小 進行計算;

計算字元串長度示例 :

-- 代碼 :

[cpp] view plaincopy

  1. /*************************************************************************
  2. >FileName:strlen_pointer.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:2014年03月17日星期一21時38分52秒
  6. ************************************************************************/
  7. #include<stdio.h>
  8. //計算字元串長度
  9. intstrlen(char*s)
  10. {
  11. //指針p記錄首地址
  12. char*p=s;
  13. //循環獲取字元串最後的字元首地址
  14. while(*p!="")
  15. p++;
  16. //字元串佔用的內存地址個數
  17. returnp-s;
  18. }
  19. intmain(intargc,char**argv)
  20. {
  21. char*c="fuckyou!!";
  22. printf("length=%d
    ",strlen(c));
  23. return0;
  24. }

-- 執行效果 :[python] view plaincopy

  1. octopus@octopus-Vostro-270s:~/code/c/pointer$gccstrlen_pointer.c
  2. octopus@octopus-Vostro-270s:~/code/c/pointer$./a.out
  3. length=10

指針差值類型 :

-- ptrdiff_t : 該類型定義在 stddef.h 頭文件中, 表示兩個指針之間的帶符號的差值;

-- size_t : 該類型定義在 stdio.h 頭文件中, size_t 可以作為 sizeof 返回的無符號整型;

指針運算一致性 : 指針運算會自動考慮其指向的元素的長度, p 指向一個類型元素 a, 不管 a 佔多少位元組, p++ 的下一個元素都指向下一個 同類型的元素;

指針之間的有效運算 : 除下面幾種合法運算之外, 其它運算都是非法的, 但不會報錯, 會警告;

-- 賦值 : 同類型指針之間的賦值運算;

-- 算數 : 指針與整數的加減運算;

-- 0相關 : 指針與0 的賦值運算, 比較運算;

2. 字元指針與函數示例

字元串常量 : 字元串常量是一個字元數組;

-- 字元串常量界定 : 字元數組以 "" 結束, 程序通過檢查 NULL 字元找到字元串的結尾;

-- 長度大於1 : 字元串常量佔據的存儲單元 比 字元的個數 多1位, 這一位是 "";

常量字元串訪問方式 : 通過指針進行訪問, 指針指向常量字元串的第一個字元, 程序可以通過這個指針操作字元串常量;

字元串定義方式 :

-- 數組 : char array[] = "fuck"; array 存放 fuck 字元串 和 "", array 地址是字元串首地址;

-- 指針 : char *c = "fuck"; 將字元串的首地址賦值給指針c, 沒有經過字元串複製;

-- 區別 : 數組 - array 指向的地址不能改變, 單個字元可以修改; 指針 - c 指向字元串常量, 可以被修改指向其它地址, 修改字元串內容沒有意義, 這樣會在創建一個字元串常量, 並將首地址賦值給指針;

示例代碼 : 分別用數組 和 指針 用法 拷貝字元串, 字元串比較;

[cpp] view plaincopy

  1. /*************************************************************************
  2. >FileName:string.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:Tue18Mar201412:34:20AMCST
  6. ************************************************************************/
  7. #include<stdio.h>
  8. /*
  9. *字元串拷貝
  10. *將source[i]賦值給density[i],每次循環i++
  11. *當density[i]==""的時候停止循環
  12. */
  13. voidstrcpy_array(char*density,char*source)
  14. {
  15. inti=0;
  16. while((density[i]=source[i])!="")
  17. i++;
  18. }
  19. /*
  20. *字元串拷貝
  21. **density++是對*density地址指向的值賦值,然後地址進行自增操作
  22. **source++是先取出source指向的地址的值,然後地址進行自增操作
  23. */
  24. voidstrcpy_pointer(char*density,char*source)
  25. {
  26. while(*density++=*source++);
  27. }
  28. /*
  29. *s[i]==t[i]前提下s[i]=""
  30. *此時返回s[i]-t[i]
  31. *如果返回0
  32. */
  33. intstrcmp_array(char*s,char*t)
  34. {
  35. inti;
  36. for(i=0;s[i]==t[i];i++)
  37. if(s[i]=="")
  38. return0;
  39. returns[i]-t[i];
  40. }
  41. intstrcmp_pointer(char*s,char*t)
  42. {
  43. for(;*s==*t;s++,t++)
  44. if(*s=="")
  45. return0;
  46. return*s-*t;
  47. }
  48. intmain(intargc,char**argv)
  49. {
  50. char*source="octopus";
  51. chardensity[10];
  52. printf("strcmp_array=%d
    ",strcmp_array(density,source));
  53. printf("strcmp_pointer=%d
    ",strcmp_pointer(density,source));
  54. strcpy_pointer(density,source);
  55. //列印字元串,使用字元串首地址替代%s;
  56. printf("source=%s
    ",source);
  57. printf("density=%s
    ",density);
  58. }

運行結果 :[python] view plaincopy

  1. [root@ip28pointer]#gccstring.c
  2. [root@ip28pointer]#./a.out
  3. strcmp_array=-239
  4. strcmp_pointer=-239
  5. source=octopus
  6. density=octopus

* 和 自增(減) 運算 :

-- *source++ : 上面的該表達式的意義是 執行 自增運算之前, source 指針指向的字元, 讀取到該字元之後, 該指針指向的地址 +1;

-- *density++ = *source++ : source指針自增前, 現將其指向的字元 賦值給 density 之前指向的地址的字元, 然後將 source 指針 +1;

-- 入棧 : *p++ = val, 這是標準的入棧操作, 將val壓入棧, 然後指針自增1, 注意, 這裡最後一個棧多加了一個1, 然後出棧的時候要先減1 在取值;

-- 出棧 : val = *--p, 這是標準的出棧操作, 現將指針減一, 然後取出指針指向的數據, 因為指針總是指向首地址, 如果我們想要取出某一段的值, 先要將指針指向首地址才可以;

3. 指針數組 指向指針的指針 示例

案例需求 :

-- 實現功能 : 在單個運算中處理長度不一的文本, 處理可變文本行數據;

-- 實際功能 : 從標準輸入流中輸入多個字元串, 每個字元串都使用指針指向字元串的首地址, 然後將指針存放到數組中, 對字元串數組進行排序, 按照字典順序輸出;

引入指針數組 :

-- 比較操作 : 對兩個字元串進行移動 比較的時候, 使用 指向它們的指針進行操作, 比較的時候直接使用下標逐一對比;

-- 拷貝操作 : 字元串拷貝的時候, 直接將指針賦值給另一個指針即可, 不用在對文本行進行操作;

-- 好處 : 消除了移動文本帶來的內存管理 和 開銷;

函數設計 :

-- 設置函數 : 讀取輸入行, 文本排序, 列印文本行, 設置上面三個函數, 在 main 函數中控制函數執行;

-- 聲明函數 : 在文件開始先聲明一下函數, 那麼在整個文件中就可以使用這個函數了, 即使函數定義在 main 函數的後面, 也可以調用;

程序要點 :

-- 輸入流讀取字元串 : 在for循環中獲取字元, 當獲取到 EOF 或者 "
" 的 或者 獲取字元超過數組大小 的時候停止獲取, 返回 獲取的字元串 和 個數;

-- 創建字元指針數組 : 當獲取到的字元串個數為0, 停止獲取字元串, 然後統計字元串個數, 根據字元串個數分配字元指針數組大小;

-- 遞歸排序 :

-- 列印數組 : 遍歷指針數組, 將指針指向的字元串列印出來;

C程序代碼 :

[cpp] view plaincopy

  1. /*************************************************************************
  2. >FileName:string_sort.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:2014年03月18日星期二12時33分19秒
  6. ************************************************************************/
  7. #include<stdio.h>
  8. #include<string.h>
  9. //定義排序的最大文本行數
  10. #defineMAXLINES100
  11. //文本行的指針數組,該數組中存放的是char類型指針
  12. char*lineptr[MAXLINES];
  13. //每行輸入最大文本數10個字元
  14. #defineMAXLEN100
  15. intreadlines(char*lineptr[],intmaxlines);
  16. voidwritelines(char*lineptr[],intnlines);
  17. voidqsort(char*v[],intleft,intright);
  18. intmain(intargc,char**argv)
  19. {
  20. intnlines;
  21. if((nlines=readlines(lineptr,MAXLINES))>=0)
  22. {
  23. qsort(lineptr,0,nlines-1);
  24. writelines(lineptr,nlines);
  25. return0;
  26. }
  27. else
  28. {
  29. printf("error:inputtoobigdata!
    ");
  30. return1;
  31. }
  32. printf("fuckmain
    ");
  33. return0;
  34. }
  35. /*
  36. *從輸入流中接收收據,最多接收max個字元,返回讀取到的字元串長度
  37. *注意:函數不能命名為getline,與stdio.h中的getline命名衝突
  38. */
  39. intget_line(char*ch,intmax,intnlines)
  40. {
  41. printf("inputthe%dcharsequence:",nlines);
  42. intc,i;
  43. /*
  44. *getchar()返回值時無符號的char類型轉換成的int類型
  45. *將int類型數據賦值給char類型,就是截取int的最後8位即一位元組賦給char變數
  46. *
  47. *循環的條件:
  48. *輸入的字元數不超過定義的MAXLEN10
  49. *獲取的字元不是EOF結束符
  50. *獲取的字元不是"
    "回車
  51. *
  52. *輸入EOF(Ctrl+D)或者回車這一行的字元串就會輸入完畢
  53. */
  54. for(i=0;i<max-1&&(c=getchar())!=EOF&&c!="
    ";i++)
  55. ch[i]=c;
  56. //給字元串加上結尾""
  57. ch[i]="";
  58. returni;
  59. }
  60. //可分配的內存共11000位元組,最大文本行數100,每行100字元,最大不會超過10000位元組
  61. #defineALLOCSIZE11000
  62. //alloc函數可分配的內存存儲區
  63. staticcharallocbuf[ALLOCSIZE];
  64. //空間分配的輔助偏移量
  65. staticchar*allocp=allocbuf;
  66. /*
  67. *分配內存
  68. */
  69. char*alloc(intn)
  70. {
  71. //判斷剩餘內存是否足夠
  72. if(allocbuf+ALLOCSIZE-allocp>=n)
  73. {
  74. //分配內存,將偏移量指向下一個空白內存
  75. allocp+=n;
  76. //注意返回分配的內存的時候,需要將指針指向已經分配內存的首地址
  77. returnallocp-n;
  78. }else
  79. return0;
  80. }
  81. intreadlines(char*lineptr[],intmaxlines)
  82. {
  83. /*
  84. *len獲取的字元串的字元個數,注意不包括"",是真實的個數
  85. *nlines初始值0,獲取的字元串個數,即字元指針數組的大小
  86. **palloc()方法分配內存的個數
  87. *line[MAXLEN]從輸入流中獲取字元串的載體
  88. */
  89. intlen,nlines;
  90. char*p,line[MAXLEN];
  91. nlines=0;
  92. /*
  93. *不停的從輸入流獲取字元串,放到line數組中,獲取的字元最多100個
  94. *如果獲取的字元個數大於0,就執行循環體內的方法
  95. */
  96. while((len=get_line(line,MAXLEN,nlines))>0)
  97. /*
  98. *如果獲取的字元串個數超過MAXLINES100個,就返回-1
  99. *如果沒有獲取到足夠的內存,就返回-1
  100. *分配的內存要多分配1個,get_line返回的函數小於
  101. */
  102. if(nlines>=MAXLINES||(p=alloc(len+1))==NULL)
  103. return-1;
  104. else
  105. {
  106. //拷貝獲取的字元串到alloc分配的內存中
  107. strcpy(p,line);
  108. //將alloc分配的內存指針放入指針數組中
  109. lineptr[nlines++]=p;
  110. }
  111. returnnlines;
  112. }
  113. /*
  114. *輸出指針數組中的指針指向的字元串
  115. *每個指針都指向一個字元串數組,不是常量
  116. */
  117. voidwritelines(char*lineptr[],intnlines)
  118. {
  119. inti;
  120. printf("
    ");
  121. //便利指針數組,將每個指針代表的字元串列印出來
  122. for(i=0;i<nlines;i++)
  123. printf("lineptr[%d]=%s
    ",i,lineptr[i]);
  124. }
  125. //數組中的兩個元素進行交換
  126. voidswap(char*v[],inti,intj)
  127. {
  128. //每個數組元素都是char*類型的,使用temp保存數組元素
  129. char*temp;
  130. //都是char*之間的數據進行賦值運算
  131. temp=v[i];
  132. v[i]=v[j];
  133. v[j]=temp;
  134. }
  135. /*
  136. *參數解析:
  137. *char*v[]:字元指針數組
  138. *intleft:排序的字元數組起始下標
  139. *intright:排序的字元數組的終止下標
  140. *qsort(array,0,3)將array中的第0個到第3個之間的字元串排序
  141. *
  142. *
  143. *strcmp(s1,s2)函數解析:
  144. *返回值<0:s1<s2
  145. *返回值=0:s1=s2
  146. *返回值>0:s1>s2
  147. */
  148. voidqsort(char*v[],intleft,intright)
  149. {
  150. inti,last;
  151. //如果數組的元素個數小於2個,返回
  152. if(left>=right)
  153. return;
  154. //交換最左邊和中間元素
  155. swap(v,left,(left+right)/2);
  156. //last記錄
  157. last=left;
  158. /*
  159. *過程解析:last指向第一個元素
  160. *從第二個元素開始遍歷整個數組,直到遍歷結束
  161. *如果遍歷的i元素小於left元素
  162. *將last下標自增,然後與i位置互換
  163. *
  164. *最終除了left之外,右邊的last個都比left小
  165. *將last與left互換,last是最大的;
  166. */
  167. for(i=left+1;i<=right;i++)
  168. if(strcmp(v[i],v[left])<0)
  169. swap(v,++last,i);
  170. swap(v,left,last);
  171. //遞歸進行left到中間的排序
  172. qsort(v,left,last-1);
  173. //遞歸進行中間到right的排序
  174. qsort(v,last+1,right);
  175. }

運行效果 :

[python] view plaincopy

  1. octopus@octopus-Vostro-270s:~/code/c/pointer$gccstring_sort.c
  2. octopus@octopus-Vostro-270s:~/code/c/pointer$./a.out
  3. inputthe0charsequence:hello
  4. inputthe1charsequence:world
  5. inputthe2charsequence:fuck
  6. inputthe3charsequence:you
  7. inputthe4charsequence:my
  8. inputthe5charsequence:load
  9. inputthe6charsequence:down
  10. inputthe7charsequence:up
  11. inputthe8charsequence:ctrl
  12. inputthe9charsequence:num
  13. inputthe10charsequence:12
  14. inputthe11charsequence:34
  15. inputthe12charsequence:56
  16. inputthe13charsequence:78
  17. inputthe14charsequence:35436
  18. inputthe15charsequence:6876
  19. inputthe16charsequence:
  20. lineptr[0]=12
  21. lineptr[1]=34
  22. lineptr[2]=35436
  23. lineptr[3]=56
  24. lineptr[4]=6876
  25. lineptr[5]=78
  26. lineptr[6]=ctrl
  27. lineptr[7]=down
  28. lineptr[8]=fuck
  29. lineptr[9]=hello
  30. lineptr[10]=load
  31. lineptr[11]=my
  32. lineptr[12]=num
  33. lineptr[13]=up
  34. lineptr[14]=world
  35. lineptr[15]=you

4. 多維數組案例

日期轉程序需求 : 將某月 某日 轉換成 一年中的 第多少天, 反之 將某天轉換成 某年的 某月某日;

-- 月日轉天 : 如 5月1日 是某一年的第幾天, 注 閏年 與 非閏年不同;

-- 天轉月日 : 將天數 轉換成 某一年的 月份 和 日期, 注意閏年;

C程序 :

[cpp] view plaincopy

  1. /*************************************************************************
  2. >FileName:multi_array.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:2014年03月18日星期二20時55分07秒
  6. ************************************************************************/
  7. #include<stdio.h>
  8. /*
  9. *該二維數組中存放的是閏年和非閏年每個月的天數
  10. *day_table[1]中存放的是非閏年每個月的天數
  11. *day_table[2]中存放的時閏年每個月的天數
  12. */
  13. staticcharday_table[2][13]={
  14. {0,31,28,31,30,31,30,31,31,30,31,30,31},
  15. {0,31,29,31,30,31,30,31,31,30,31,30,31}
  16. };
  17. /*
  18. *四年一潤,百年不潤,四百年再潤
  19. */
  20. intleap(intyear)
  21. {
  22. return(year%4==0&&year%100!=0)||(year%400==0);
  23. }
  24. /*
  25. *遍歷每月的月份數,將每月的天數累加加上日的天數
  26. *得出的結果就是某日期在某年的天數
  27. */
  28. intday_of_year(intyear,intmonth,intday)
  29. {
  30. inti;
  31. for(i=1;i<month;i++)
  32. day+=day_table[leap(year)][i];
  33. returnday;
  34. }
  35. /*
  36. *計算某年的天數是具體的幾月幾日
  37. *從1開始遍歷二維數組的某一年的月份天數
  38. *如果天數大於月份天數,那麼年天數減去月份天數,然後月份自增
  39. *一直循環到年天數小於月份天數
  40. *那麼此時循環月份自增的變數就是月份數,剩餘的年天數就是日
  41. *
  42. */
  43. voiddate_of_year(intyear,intyear_day,int*pmonth,int*pday)
  44. {
  45. inti,lp;
  46. lp=leap(year);
  47. for(i=1;year_day>day_table[lp][i];i++)
  48. year_day-=day_table[lp][i];
  49. *pmonth=i;
  50. *pday=year_day;
  51. }
  52. intmain(intargc,char**argv)
  53. {
  54. /*
  55. *注意指針使用之前一定要初始化,如果指針不初始化,就不能使用
  56. *沒有初始化的指針,不能作為函數的參數
  57. */
  58. intmonth,day;
  59. date_of_year(2014,67,&month,&day);
  60. printf("2014-3-8isthe%ddayoftheyear
    ",day_of_year(2014,3,8));
  61. printf("the67dayof2014is%dmonth%dday
    ",month,day);
  62. return0;
  63. }

執行結果 :[python] view plaincopy

  1. octopus@octopus-Vostro-270s:~/code/c/pointer$gccmulti_array.c
  2. octopus@octopus-Vostro-270s:~/code/c/pointer$./a.out
  3. 2014-3-8isthe67dayoftheyear
  4. the67dayof2014is3month8day

二維數組作參數 : 必須聲明 列數, 行數可以不進行聲明;

-- 函數調用二維數組本質 : 函數調用的傳遞的是指針, 指針指向一個數組, 這個數組存放的是指針元素, 每個指針都指向一個一維數組;

-- 必須知道一維數組大小 : 傳入的只是一個指針, 如何找到數組中的第二個指針呢, 就需要知道一維數組的大小, 傳入的指針 加上 一維數組地址 就是 第二個指針的大小, 如果沒有一維數組大小, 那麼就找不到其它的指針了;

二維數組參數正確聲明 :

-- 帶所有的參數 : fun(int day_table[2][13]);

-- 帶列數, 不帶行數 : fun(int day_table[][13]);

-- 指針參數 : fun(int (*day_table)[13]) , 代表參數是一個指針, 這個指針指向一個 由 13個元素組成的一維數組;

-- 錯誤情況 : fun(int *dat_table[13]) 傳入的時一個 存放有 13個指針元素的 一維數組;

-- 錯誤情況 : fun(int day_table[2][]) 沒有列數, 傳入的時候只傳入了首地址, 無法找到第二個指針;

5. 指針數組初始化

示例代碼 :

[cpp] view plaincopy

  1. /*************************************************************************
  2. >FileName:montn_name.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:Wed19Mar201412:58:48AMCST
  6. ************************************************************************/
  7. #include<stdio.h>
  8. char*month_name(intn)
  9. {
  10. /*
  11. *初始化指針數組,指針數組中的元素指向一個字元串
  12. */
  13. staticchar*name[]={
  14. "Illegalmonth",
  15. "January","Febrary","March",
  16. "April","May","June",
  17. "July","August","September",
  18. "October","November","December"
  19. };
  20. //返回一個指針,這個指針指向字元串
  21. return(n<1||n>12)?name[0]:name[n];
  22. }
  23. intmain(intargc,char**argv)
  24. {
  25. printf("month2is%s
    ",month_name(2));
  26. return0;
  27. }

執行結果 :[python] view plaincopy

  1. [root@ip28pointer]#gccmontn_name.c
  2. [root@ip28pointer]#./a.out
  3. month2isFebrary

指針數組初始化 : char *name[] 是一個指針數組, 這是一個一維數組;

-- 指針賦值 : 字元串常量 代表一個指向該常量首地址的指針, 可以將字元串常量賦值給上面的 一維指針數組;

6. 區分指針數組 與 二維數組

舉例 :

int array[2][5];

int *arrayp[2];

二維數組 : 上面的 array[2][5] 是二維數組;

-- 空間分配 : 分配了 2 * 5 * sizeof(int) 大小的內存空間;

-- 計算元素地址 : 5 * row + col 是 array[row][col]的地址;

指針數組 : *array[2] 是指針數組;

-- 空間分配 : 分配了10個指針, 沒有對指針進行初始化, 必須進行手動初始化, 指針指向的一維數組長度可變, 不固定;

-- 作用 : 指針數組最主要的作用是存放不同長度的字元串;

指針數組示常式序 :

[cpp] view plaincopy

  1. /*************************************************************************
  2. >FileName:montn_name.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:Wed19Mar201412:58:48AMCST
  6. ************************************************************************/
  7. #include<stdio.h>
  8. char*month_name(intn)
  9. {
  10. /*
  11. *初始化指針數組,指針數組中的元素指向一個字元串
  12. */
  13. staticchar*name[]={
  14. "Illegalmonth",
  15. "January","Febrary","March",
  16. "April","May","June",
  17. "July","August","September",
  18. "October","November","December"
  19. };
  20. printf("sizeof(name)=%d
    ",sizeof(name));
  21. //返回一個指針,這個指針指向字元串
  22. return(n<1||n>12)?name[0]:name[n];
  23. }
  24. intmain(intargc,char**argv)
  25. {
  26. printf("month2is%s
    ",month_name(2));
  27. return0;
  28. }

執行結果 :[python] view plaincopy

  1. [root@ip28pointer]#gccmontn_name.c
  2. [root@ip28pointer]#./a.out
  3. sizeof(name)=104
  4. month2isFebrary

二維數組示常式序 :

[cpp] view plaincopy

  1. /*************************************************************************
  2. >FileName:montn_name.c
  3. >Author:octopus
  4. >Mail:octopus_work.163.com
  5. >CreatedTime:Wed19Mar201412:58:48AMCST
  6. ************************************************************************/
  7. #include<stdio.h>
  8. char*month_name(intn)
  9. {
  10. /*
  11. *初始化指針數組,指針數組中的元素指向一個字元串
  12. */
  13. staticcharname[][20]={
  14. "Illegalmonth",
  15. "January","Febrary","March",
  16. "April","May","June",
  17. "July","August","September",
  18. "October","November","December"
  19. };
  20. printf("sizeof(name)=%d
    ",sizeof(name));
  21. //返回一個指針,這個指針指向字元串
  22. return(n<1||n>12)?name[0]:name[n];
  23. }
  24. intmain(intargc,char**argv)
  25. {
  26. printf("month2is%s
    ",month_name(2));
  27. return0;
  28. }

執行結果 :[python] view plaincopy

  1. [root@ip28pointer]#gccmonth_array.c
  2. [root@ip28pointer]#./a.out
  3. sizeof(name)=260
  4. month2isFebrary

對比 : 二維數組 佔用了 260 位元組內存, 指針數組佔用了 104位元組的內存;

.

作者:萬境絕塵

轉載請註明出處:http://blog.csdn.net/shulianghan/article/details/21402047

.


推薦閱讀:

第六十二章 語言
法語和西班牙語究竟有多接近?
從上古雅言到今天的普通話,中國官方語言如何形成統一的?
語言7

TAG:語言 | 指針 | 多維 | C語言 | 數組 |