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, 當偏移量 等於 數組大小, 說明內存全部分配完畢;

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


代碼

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

#include<stdio.h>

//用於內存分配載體的大數組大小
#define ALLOCSIZE 1000
/*
 * 該數組就是用於內存分配的主體, 
 * 設置爲static , 意味着只能在本文件中訪問, 在其它文件中不能訪問
 */
static char alloc_buf[ALLOCSIZE];
/*
 * 將alloc_buf 數組的首地址賦值給allocp字符指針
 * 對allocp 進行算數運算, 每次加減都是 char * 運算數
 * allocp的值就可以代表所分配內存的首地址
 */
static char *allocp = alloc_buf;

/*
 * 分配n個char類型數組的內存, 
 * 如果分配成功, 返回分配的內存的指針,
 * 如果分配失敗, 返回0
 */
char *alloc(int n)
{
	//如果大數組剩餘的空間可以分配, 那麼就進行分配
	if(alloc_buf + ALLOCSIZE - allocp >= n)
	{
		//分配空間, allocp 指向下一個空間的內存首地址
		allocp += n;
		//返回分配的空間首地址
		return allocp - n;
	}else //如果數組剩餘空間不足, 返回0
	{
		return 0;
	}
}

/*
 * 釋放分配的內存
 * 釋放內存就是將allocp 指針地址指向 要釋放的內存指針首地址
 */
void afree(char *p)
{
	//釋放內存的前提是 內存必須是大於數組首地址, 小於數組尾地址
	if(p >= alloc_buf && p < alloc_buf + ALLOCSIZE)
	{
		allocp = p;
		printf("allocp = %p \n", allocp);
	}
}

int main(int argc, char **argv)
{
	char *p1;
	char *p2;
	char *p3;
	char *p4;

	//打印數組首地址
	printf("alloc_buf = %p \n", alloc_buf);

	//分配300個字符內存
	p1 = alloc(300);
	printf("char *p1 = alloc(300), p1 = %p \n", p1);

	p2 = alloc(300);
	printf("char *p2 = alloc(300), p2 = %p \n", p2);

	p3 = alloc(300);
	printf("char *p3 = alloc(300), p3 = %p \n", p3);

	//上面已經分配了900了, 在分配就溢出了, 這裏alloc()函數返回0
	p4 = alloc(300);
	printf("char *p4 = alloc(300), p4 = %p \n", p4);

	afree(p4);
	afree(p3);
	afree(p2);
	afree(p1);
}

執行結果 :

  1. octopus@octopus-Vostro-270s:~/code/c/pointer$ gcc alloc_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   
octopus@octopus-Vostro-270s:~/code/c/pointer$ gcc alloc_afree.c 
octopus@octopus-Vostro-270s:~/code/c/pointer$ ./a.out 
alloc_buf = 0x804a060 
char *p1 = alloc(300), p1 = 0x804a060 
char *p2 = alloc(300), p2 = 0x804a18c 
char *p3 = alloc(300), p3 = 0x804a2b8 
char *p4 = alloc(300), p4 = (nil) 
allocp = 0x804a2b8 
allocp = 0x804a18c 
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 是一個特殊值;


指針運算

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

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


計算字符串長度示例

-- 代碼

  1. /************************************************************************* 
  2.     > File Name: strlen_pointer.c 
  3.     > Author: octopus 
  4.     > Mail: octopus_work.163.com  
  5.     > Created Time: 2014年03月17日 星期一 21時38分52秒 
  6.  ************************************************************************/  
  7.   
  8. #include<stdio.h>   
  9.   
  10. //計算字符串長度   
  11. int strlen(char *s)  
  12. {  
  13.     //指針 p 記錄首地址   
  14.     char *p = s;  
  15.     //循環獲取字符串最後的字符首地址   
  16.     while(*p != '\0')  
  17.         p++;  
  18.     //字符串佔用的內存地址個數   
  19.     return p - s;  
  20. }  
  21.   
  22. int main(int argc, char **argv)  
  23. {  
  24.     char *c = "fuck you!!";  
  25.   
  26.     printf("length = %d \n", strlen(c));  
  27.   
  28.     return 0;  
  29. }  
/*************************************************************************
    > File Name: strlen_pointer.c
    > Author: octopus
    > Mail: octopus_work.163.com 
    > Created Time: 2014年03月17日 星期一 21時38分52秒
 ************************************************************************/

#include<stdio.h>

//計算字符串長度
int strlen(char *s)
{
	//指針 p 記錄首地址
	char *p = s;
	//循環獲取字符串最後的字符首地址
	while(*p != '\0')
		p++;
	//字符串佔用的內存地址個數
	return p - s;
}

int main(int argc, char **argv)
{
	char *c = "fuck you!!";

	printf("length = %d \n", strlen(c));

	return 0;
}

-- 執行效果

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


指針差值類型

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

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


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


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

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

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

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



2. 字符指針與函數示例



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

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

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


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


字符串定義方式

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

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

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



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

  1. /************************************************************************* 
  2.     > File Name: string.c 
  3.     > Author: octopus 
  4.     > Mail: octopus_work.163.com  
  5.     > Created Time: Tue 18 Mar 2014 12:34:20 AM CST 
  6.  ************************************************************************/  
  7.   
  8. #include<stdio.h>   
  9.   
  10. /* 
  11.  * 字符串拷貝 
  12.  * 將 source[i] 賦值給 density[i], 每次循環 i++  
  13.  * 當density[i] == '\0'的時候停止循環 
  14.  */   
  15. void strcpy_array(char *density, char *source)  
  16. {  
  17.         int i = 0;  
  18.         while((density[i] = source[i]) != '\0')  
  19.                 i++;  
  20. }   
  21.   
  22. /* 
  23.  * 字符串拷貝 
  24.  * *density++ 是對*density地址指向的值賦值, 然後地址進行自增操作 
  25.  * *source++ 是先取出source 指向的地址的值, 然後地址進行自增操作 
  26.  */  
  27. void strcpy_pointer(char *density, char *source)  
  28. {  
  29.         while(*density++ = *source++);  
  30. }  
  31.   
  32. /* 
  33.  * s[i] == t[i] 前提下 s[i] = '\0' 
  34.  * 此時 返回 s[i] - t[i]  
  35.  * 如果返回0  
  36.  */  
  37. int strcmp_array(char *s, char *t)  
  38. {  
  39.         int i;  
  40.         for(i = 0; s[i] == t[i]; i++)  
  41.                 if(s[i] == '\0')  
  42.                         return 0;  
  43.         return s[i] - t[i];  
  44. }  
  45.   
  46. int strcmp_pointer(char *s, char *t)  
  47. {  
  48.         for(; *s == *t; s++, t++)  
  49.                 if(*s == '\0')  
  50.                         return 0;  
  51.         return *s - *t;  
  52. }  
  53.   
  54. int main(int argc, char **argv)  
  55. {  
  56.         char *source = "octopus";  
  57.         char density[10];  
  58.   
  59.         printf("strcmp_array = %d \n", strcmp_array(density, source));  
  60.         printf("strcmp_pointer = %d \n", strcmp_pointer(density, source));  
  61.   
  62.         strcpy_pointer(density, source);  
  63.   
  64.         //打印字符串, 使用 字符串首地址 替代 %s;   
  65.         printf("source = %s \n", source);  
  66.         printf("density = %s \n", density);  
  67. }  
/*************************************************************************
    > File Name: string.c
    > Author: octopus
    > Mail: octopus_work.163.com 
    > Created Time: Tue 18 Mar 2014 12:34:20 AM CST
 ************************************************************************/

#include<stdio.h>

/*
 * 字符串拷貝
 * 將 source[i] 賦值給 density[i], 每次循環 i++ 
 * 當density[i] == '\0'的時候停止循環
 */ 
void strcpy_array(char *density, char *source)
{
        int i = 0;
        while((density[i] = source[i]) != '\0')
                i++;
} 

/*
 * 字符串拷貝
 * *density++ 是對*density地址指向的值賦值, 然後地址進行自增操作
 * *source++ 是先取出source 指向的地址的值, 然後地址進行自增操作
 */
void strcpy_pointer(char *density, char *source)
{
        while(*density++ = *source++);
}

/*
 * s[i] == t[i] 前提下 s[i] = '\0'
 * 此時 返回 s[i] - t[i] 
 * 如果返回0 
 */
int strcmp_array(char *s, char *t)
{
        int i;
        for(i = 0; s[i] == t[i]; i++)
                if(s[i] == '\0')
                        return 0;
        return s[i] - t[i];
}

int strcmp_pointer(char *s, char *t)
{
        for(; *s == *t; s++, t++)
                if(*s == '\0')
                        return 0;
        return *s - *t;
}

int main(int argc, char **argv)
{
        char *source = "octopus";
        char density[10];

        printf("strcmp_array = %d \n", strcmp_array(density, source));
        printf("strcmp_pointer = %d \n", strcmp_pointer(density, source));

        strcpy_pointer(density, source);

        //打印字符串, 使用 字符串首地址 替代 %s;
        printf("source = %s \n", source);
        printf("density = %s \n", density);
}

運行結果

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


* 和 自增(減) 運算

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

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

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

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



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



案例需求

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

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


引入指針數組

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

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

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


函數設計

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

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


程序要點

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

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

-- 遞歸排序

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



C程序代碼

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

#include<stdio.h>
#include<string.h>

//定義排序的最大文本行數
#define MAXLINES 100

//文本行的指針數組, 該數組中存放的是 char 類型指針
char *lineptr[MAXLINES];

//每行輸入最大文本數 10 個字符
#define MAXLEN 100


int readlines(char *lineptr[], int maxlines);
void writelines(char *lineptr[], int nlines);
void qsort(char *v[], int left, int right);


int main(int argc, char **argv)
{
	int nlines;

	if((nlines = readlines(lineptr, MAXLINES)) >= 0)
	{
		qsort(lineptr, 0, nlines - 1);
		writelines(lineptr, nlines);
		return 0;
	}
	else
	{
		printf("error : input too big data ! \n");
		return 1;
	}

	printf("fuck main \n");
	return 0;
}

/*
 * 從輸入流中接收收據, 最多接收 max 個字符, 返回讀取到的字符串長度
 * 注意 : 函數不能命名爲 getline, 與stdio.h 中的 getline 命名衝突
 */
int get_line(char *ch, int max, int nlines)
{
	printf("input the %d char sequence : ", nlines);
	int c, i;
	/*
	 * getchar() 返回值 時 無符號的 char 類型轉換成的 int 類型
	 * 將int 類型數據 賦值給 char 類型, 就是截取 int 的最後8位 即一字節賦給char變量
	 *
	 * 循環的條件 : 
	 *	輸入的字符數不超過 定義的 MAXLEN 10
	 *	獲取的字符不是 EOF 結束符
	 *	獲取的字符不是 '\n' 回車
	 *
	 *	輸入 EOF(Ctrl + D) 或者 回車 這一行的字符串就會輸入完畢
	 */
	for(i = 0; i < max - 1 && (c = getchar()) != EOF && c != '\n'; i++)
		ch[i] = c;
	//給字符串加上結尾 '\0'
	ch[i] = '\0';
	return i;
}


//可分配的內存共 11000 字節, 最大文本行數 100, 每行 100字符, 最大不會超過 10000字節
#define ALLOCSIZE 11000
//alloc函數可分配的內存存儲區
static char allocbuf[ALLOCSIZE];
//空間分配的輔助偏移量
static char *allocp = allocbuf;

/*
 * 分配內存
 */
char *alloc(int n)
{
	//判斷剩餘內存是否足夠
	if(allocbuf + ALLOCSIZE - allocp >= n)
	{
		//分配內存, 將偏移量指向下一個空白內存
		allocp += n;
		//注意返回分配的內存的時候, 需要將指針指向已經分配內存的首地址
		return allocp - n;
	}else
		return 0;
}


int readlines(char *lineptr[], int maxlines)
{
	/*
	 * len 獲取的字符串的字符個數, 注意 不包括 '\0', 是真實的個數
	 * nlines 初始值0, 獲取的字符串個數, 即字符指針數組的大小
	 * *p alloc()方法分配內存的個數
	 * line[MAXLEN] 從輸入流中獲取字符串的載體
	 */
	int len, nlines;
	char *p, line[MAXLEN];
	nlines = 0;

	/*
	 * 不停的從輸入流獲取字符串, 放到 line 數組中, 獲取的字符最多100個
	 * 如果獲取的字符個數大於0, 就執行循環體內的方法
	 */
	while((len = get_line(line, MAXLEN, nlines)) > 0)
		/*
		 * 如果獲取的字符串個數 超過 MAXLINES 100 個, 就返回 -1
		 * 如果沒有獲取到足夠的內存, 就返回 -1
		 * 分配的內存要多分配1個, get_line 返回的函數小於
		 */
		if(nlines  >= MAXLINES || (p = alloc(len + 1)) == NULL)
			return -1;
		else
		{
			//拷貝獲取的字符串 到 alloc 分配的內存中
			strcpy(p, line);
			//將 alloc 分配的內存 指針 放入 指針數組中
			lineptr[nlines++] = p;
		}
	return nlines;
}

/*
 * 輸出指針數組 中 的指針 指向的字符串
 * 每個指針都指向一個字符串數組, 不是常量
 */
void writelines(char *lineptr[], int nlines)
{
	int i;
	printf("\n");
	//便利指針數組, 將每個指針代表的字符串打印出來
	for(i = 0; i < nlines; i++)
		printf("lineptr[%d] = %s\n", i, lineptr[i]);
}

//數組中的兩個元素進行交換
void swap(char *v[], int i, int j)
{
	//每個數組元素都是 char * 類型的, 使用 temp 保存數組元素
	char *temp;

	//都是 char * 之間的數據進行賦值運算
	temp = v[i];
	v[i] = v[j];
	v[j] = temp;
}

/*
 * 參數解析 : 
 *	char *v[] : 字符指針數組
 *	int left : 排序的字符數組起始下標
 *	int right : 排序的字符數組的終止下標
 *	qsort(array, 0, 3) 將 array 中的 第0個 到 第3個 之間的字符串排序
 *
 *
 * strcmp(s1, s2)函數解析 :
 *	返回值 <0 : s1 < s2
 *	返回值 =0 : s1 = s2
 *	返回值 >0 : s1 > s2
 */
void qsort(char *v[], int left, int right)
{
	int i, last;
	//如果數組的元素個數小於2個, 返回
	if(left >= right)
		return;

	//交換最左邊 和 中間元素
	swap(v, left, (left + right) / 2);
	//last 記錄
	last = left;
	/*
	 * 過程解析 : last 指向第一個元素
	 * 從第二個元素開始遍歷整個數組, 直到遍歷結束
	 * 如果遍歷的i元素 小於 left 元素
	 * 將last下標自增, 然後 與 i 位置互換
	 *
	 * 最終 除了 left 之外, 右邊的last 個都比left小
	 * 將 last 與 left 互換, last 是最大的;
	 */
	for(i = left + 1; i <= right; i++)
		if(strcmp(v[i], v[left]) < 0)
			swap(v, ++last, i);
	swap(v, left, last);

	//遞歸進行 left 到 中間 的排序
	qsort(v, left, last - 1);
	//遞歸進行 中間 到 right 的排序
	qsort(v, last + 1, right);
}


運行效果

  1. octopus@octopus-Vostro-270s:~/code/c/pointer$ gcc string_sort.c   
  2. octopus@octopus-Vostro-270s:~/code/c/pointer$ ./a.out   
  3. input the 0 char sequence : hello  
  4. input the 1 char sequence : world  
  5. input the 2 char sequence : fuck  
  6. input the 3 char sequence : you  
  7. input the 4 char sequence : my  
  8. input the 5 char sequence : load  
  9. input the 6 char sequence : down  
  10. input the 7 char sequence : up  
  11. input the 8 char sequence : ctrl  
  12. input the 9 char sequence : num  
  13. input the 10 char sequence : 12  
  14. input the 11 char sequence : 34  
  15. input the 12 char sequence : 56  
  16. input the 13 char sequence : 78  
  17. input the 14 char sequence : 35436  
  18. input the 15 char sequence : 6876  
  19. input the 16 char sequence :   
  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  
octopus@octopus-Vostro-270s:~/code/c/pointer$ gcc string_sort.c 
octopus@octopus-Vostro-270s:~/code/c/pointer$ ./a.out 
input the 0 char sequence : hello
input the 1 char sequence : world
input the 2 char sequence : fuck
input the 3 char sequence : you
input the 4 char sequence : my
input the 5 char sequence : load
input the 6 char sequence : down
input the 7 char sequence : up
input the 8 char sequence : ctrl
input the 9 char sequence : num
input the 10 char sequence : 12
input the 11 char sequence : 34
input the 12 char sequence : 56
input the 13 char sequence : 78
input the 14 char sequence : 35436
input the 15 char sequence : 6876
input the 16 char sequence : 
lineptr[0] = 12
lineptr[1] = 34
lineptr[2] = 35436
lineptr[3] = 56
lineptr[4] = 6876
lineptr[5] = 78
lineptr[6] = ctrl
lineptr[7] = down
lineptr[8] = fuck
lineptr[9] = hello
lineptr[10] = load
lineptr[11] = my
lineptr[12] = num
lineptr[13] = up
lineptr[14] = world
lineptr[15] = you




4. 多維數組案例



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

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

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


C程序

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

#include<stdio.h>

/*
 * 該二維數組中存放的是 閏年 和 非閏年 每個月的天數
 * day_table[1] 中存放的是 非閏年 每個月的天數
 * day_table[2] 中存放的時 閏年 每個月的天數
 */
static char day_table[2][13] = {
	{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
	{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

/*
 * 四年一潤, 百年不潤, 四百年再潤
 */
int leap(int year)
{
	return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

/*
 * 遍歷每月的月份數, 將每月的天數累加 加上 日的天數
 * 得出的結果就是 某日期 在某年的天數
 */
int day_of_year(int year, int month, int day)
{
	int i;
	for(i = 1; i < month; i++)
		day += day_table[leap(year)][i];
	return day;
}

/*
 * 計算 某年的天數 是具體的 幾月幾日
 * 從 1 開始遍歷二維數組的 某一年的月份天數
 * 如果 天數 大於 月份天數, 那麼 年天數 減去 月份天數, 然後月份自增
 * 一直循環到 年天數 小於 月份天數
 * 那麼此時循環 月份自增的變量就是月份數, 剩餘的 年天數就是 日
 * 
 */
void date_of_year(int year, int year_day, int *pmonth, int *pday)
{
	int i, lp;
	lp = leap(year);
	for(i = 1; year_day > day_table[lp][i]; i++)
		year_day -= day_table[lp][i];\
	*pmonth = i;
	*pday = year_day;
}

int main(int argc, char **argv)
{
	/*
	 * 注意指針使用之前一定要初始化, 如果指針不初始化, 就不能使用
	 * 沒有初始化的指針, 不能作爲函數的參數
	 */
	int month, day;
	date_of_year(2014, 67, &month, &day);

	printf("2014-3-8 is the %d day of the year \n", day_of_year(2014, 3, 8));
	printf("the 67 day of 2014 is %d month %d day \n", month, day);

	return 0;
}

執行結果

  1. octopus@octopus-Vostro-270s:~/code/c/pointer$ gcc multi_array.c   
  2. octopus@octopus-Vostro-270s:~/code/c/pointer$ ./a.out   
  3. 2014-3-8 is the 67 day of the year   
  4. the 67 day of 2014 is 3 month 8 day   
octopus@octopus-Vostro-270s:~/code/c/pointer$ gcc multi_array.c 
octopus@octopus-Vostro-270s:~/code/c/pointer$ ./a.out 
2014-3-8 is the 67 day of the year 
the 67 day of 2014 is 3 month 8 day 


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

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

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


二維數組參數正確聲明

-- 帶所有的參數 : 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. 指針數組初始化


示例代碼

  1. /************************************************************************* 
  2.     > File Name: montn_name.c 
  3.     > Author: octopus 
  4.     > Mail: octopus_work.163.com  
  5.     > Created Time: Wed 19 Mar 2014 12:58:48 AM CST 
  6.  ************************************************************************/  
  7.   
  8. #include<stdio.h>   
  9.   
  10. char *month_name(int n)  
  11. {  
  12.         /* 
  13.          * 初始化指針數組, 指針數組中的元素指向一個字符串 
  14.          */  
  15.         static char *name[] = {  
  16.                 "Illegal month",   
  17.                 "January""Febrary""March",  
  18.                 "April""May""June",  
  19.                 "July""August""September",  
  20.                 "October""November""December"  
  21.         };  
  22.   
  23.         //返回一個指針, 這個指針指向字符串   
  24.         return (n < 1 || n > 12) ? name[0] : name[n];  
  25. }  
  26.   
  27. int main(int argc, char **argv)  
  28. {  
  29.         printf("month 2 is %s \n", month_name(2));  
  30.         return 0;  
  31. }  
/*************************************************************************
    > File Name: montn_name.c
    > Author: octopus
    > Mail: octopus_work.163.com 
    > Created Time: Wed 19 Mar 2014 12:58:48 AM CST
 ************************************************************************/

#include<stdio.h>

char *month_name(int n)
{
        /*
         * 初始化指針數組, 指針數組中的元素指向一個字符串
         */
        static char *name[] = {
                "Illegal month", 
                "January", "Febrary", "March",
                "April", "May", "June",
                "July", "August", "September",
                "October", "November", "December"
        };

        //返回一個指針, 這個指針指向字符串
        return (n < 1 || n > 12) ? name[0] : name[n];
}

int main(int argc, char **argv)
{
        printf("month 2 is %s \n", month_name(2));
        return 0;
}

執行結果

  1. [root@ip28 pointer]# gcc montn_name.c    
  2. [root@ip28 pointer]# ./a.out    
  3. month 2 is Febrary   
[root@ip28 pointer]# gcc montn_name.c 
[root@ip28 pointer]# ./a.out 
month 2 is Febrary 


指針數組初始化 : 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個指針, 沒有對指針進行初始化, 必須進行手動初始化, 指針指向的一維數組長度可變, 不固定;

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


指針數組示例程序 :

  1. /************************************************************************* 
  2.     > File Name: montn_name.c 
  3.     > Author: octopus 
  4.     > Mail: octopus_work.163.com  
  5.     > Created Time: Wed 19 Mar 2014 12:58:48 AM CST 
  6.  ************************************************************************/  
  7.   
  8. #include<stdio.h>   
  9.   
  10. char *month_name(int n)  
  11. {  
  12.         /* 
  13.          * 初始化指針數組, 指針數組中的元素指向一個字符串 
  14.          */  
  15.         static char *name[] = {  
  16.                 "Illegal month",   
  17.                 "January""Febrary""March",  
  18.                 "April""May""June",  
  19.                 "July""August""September",  
  20.                 "October""November""December"  
  21.         };  
  22.   
  23.         printf("sizeof(name) = %d \n"sizeof(name));  
  24.         //返回一個指針, 這個指針指向字符串   
  25.         return (n < 1 || n > 12) ? name[0] : name[n];  
  26. }  
  27.   
  28. int main(int argc, char **argv)  
  29. {  
  30.         printf("month 2 is %s \n", month_name(2));  
  31.         return 0;  
  32. }  
/*************************************************************************
    > File Name: montn_name.c
    > Author: octopus
    > Mail: octopus_work.163.com 
    > Created Time: Wed 19 Mar 2014 12:58:48 AM CST
 ************************************************************************/

#include<stdio.h>

char *month_name(int n)
{
        /*
         * 初始化指針數組, 指針數組中的元素指向一個字符串
         */
        static char *name[] = {
                "Illegal month", 
                "January", "Febrary", "March",
                "April", "May", "June",
                "July", "August", "September",
                "October", "November", "December"
        };

        printf("sizeof(name) = %d \n", sizeof(name));
        //返回一個指針, 這個指針指向字符串
        return (n < 1 || n > 12) ? name[0] : name[n];
}

int main(int argc, char **argv)
{
        printf("month 2 is %s \n", month_name(2));
        return 0;
}

執行結果

  1. [root@ip28 pointer]# gcc montn_name.c                                  
  2. [root@ip28 pointer]# ./a.out    
  3. sizeof(name) = 104   
  4. month 2 is Febrary   
[root@ip28 pointer]# gcc montn_name.c                               
[root@ip28 pointer]# ./a.out 
sizeof(name) = 104 
month 2 is Febrary 


二維數組示例程序

  1. /************************************************************************* 
  2.     > File Name: montn_name.c 
  3.     > Author: octopus 
  4.     > Mail: octopus_work.163.com  
  5.     > Created Time: Wed 19 Mar 2014 12:58:48 AM CST 
  6.  ************************************************************************/  
  7.   
  8. #include<stdio.h>   
  9.   
  10. char *month_name(int n)  
  11. {  
  12.         /* 
  13.          * 初始化指針數組, 指針數組中的元素指向一個字符串 
  14.          */  
  15.         static char name[][20] = {  
  16.                 "Illegal month",   
  17.                 "January""Febrary""March",  
  18.                 "April""May""June",  
  19.                 "July""August""September",  
  20.                 "October""November""December"  
  21.         };  
  22.   
  23.         printf("sizeof(name) = %d \n"sizeof(name));  
  24.   
  25.         //返回一個指針, 這個指針指向字符串   
  26.         return (n < 1 || n > 12) ? name[0] : name[n];  
  27. }  
  28.   
  29. int main(int argc, char **argv)  
  30. {  
  31.         printf("month 2 is %s \n", month_name(2));  
  32.         return 0;  
  33. }  
/*************************************************************************
    > File Name: montn_name.c
    > Author: octopus
    > Mail: octopus_work.163.com 
    > Created Time: Wed 19 Mar 2014 12:58:48 AM CST
 ************************************************************************/

#include<stdio.h>

char *month_name(int n)
{
        /*
         * 初始化指針數組, 指針數組中的元素指向一個字符串
         */
        static char name[][20] = {
                "Illegal month", 
                "January", "Febrary", "March",
                "April", "May", "June",
                "July", "August", "September",
                "October", "November", "December"
        };

        printf("sizeof(name) = %d \n", sizeof(name));

        //返回一個指針, 這個指針指向字符串
        return (n < 1 || n > 12) ? name[0] : name[n];
}

int main(int argc, char **argv)
{
        printf("month 2 is %s \n", month_name(2));
        return 0;
}

執行結果

  1. [root@ip28 pointer]# gcc month_array.c              
  2. [root@ip28 pointer]# ./a.out    
  3. sizeof(name) = 260   
  4. month 2 is Febrary   
[root@ip28 pointer]# gcc month_array.c           
[root@ip28 pointer]# ./a.out 
sizeof(name) = 260 
month 2 is Febrary 


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


.

作者 : 萬境絕塵

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章