天天看點

【嵌入式開發】C語言 指針數組 多元數組

.

​作者​ :​ 萬境絕塵​

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, 當偏移量 等于 數組大小, 說明記憶體全部配置設定完畢;

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

​代碼​ : 

/*************************************************************************
    > 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);
}      

​執行結果​ :

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()函數示例圖​ : 

【嵌入式開發】C語言 指針數組 多元數組

--​ afree()函數示例圖​ : 

【嵌入式開發】C語言 指針數組 多元數組

​指針初始化​ : 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 是一個特殊值;

​指針運算​ : 

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

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

​計算字元串長度示例​ : 

-- ​代碼​ : 

/*************************************************************************
    > 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;
}      

--

​執行效果​ : 

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 指向字元串常量, 可以被修改指向其它位址, 修改字元串内容沒有意義, 這樣會在建立一個字元串常量, 并将首位址指派給指針;

【嵌入式開發】C語言 指針數組 多元數組

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

/*************************************************************************
    > 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);
}      

​運作結果​ : 

[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程式代碼​ : 

/*************************************************************************
    > 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);
}      

​運作效果​ : 

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程式 ​: 

/*************************************************************************
    > 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;
}      

​執行結果​ : 

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. 指針數組初始化

​示例代碼 ​: 

/*************************************************************************
    > 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;
}      

​執行結果​ : 

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

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

​指針數組示例程式​ :

/*************************************************************************
    > 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;
}      

​執行結果​ : 

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

​二維數組示例程式​ : 

/*************************************************************************
    > 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;
}      

​執行結果​ : 

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

​對比​ : 二維數組 占用了 260 位元組記憶體, 指針數組占用了 104位元組的記憶體;  

.

​作者​ :​ 萬境絕塵​