【嵌入式开发】C语言 指针数组 多维数组
.
作者 : 萬境絕塵
轉(zhuǎn)載請注明出處 :?http://blog.csdn.net/shulianghan/article/details/21402047
.?
1. 地址算數(shù)運(yùn)算示例
指針?biāo)銛?shù)運(yùn)算 : int *p, array[5]; p = array; p 指向一個(gè) int 數(shù)組元素, p + i 的地址時(shí)數(shù)組中第 i 個(gè)元素的地址, 即 p + i 指向 第 i 個(gè)元素;
存儲分配示例函數(shù) :?
-- char *alloc(int n) 函數(shù) : 傳入分配的字符個(gè)數(shù), 返回連續(xù)字符存儲單元指針, 這個(gè)指針可以存儲 n 個(gè)字符元素;
-- int afree(char *p) 函數(shù) : 釋放分配的內(nèi)存空間;
-- 缺陷 : 分配內(nèi)存的時(shí)候, 有一個(gè)偏移量, 偏移量的大小代表已經(jīng)分配了多少內(nèi)存, 釋放內(nèi)存必須按照分配內(nèi)存的順序釋放, 否則偏移量就會亂;
-- 內(nèi)存分配原理 : 設(shè)置一個(gè)大數(shù)組, 內(nèi)存分配就分配這個(gè)數(shù)組的中的空間, alloc 和 afree 函數(shù)操作的是指針, 不是數(shù)組, 因此這個(gè)數(shù)組可以隱藏, 將數(shù)組定義為static 類型, 那么在其它文件中, 不能訪問該數(shù)組, 設(shè)置一個(gè)偏移量, 當(dāng)分配 n 個(gè)元素, 偏移量就加上 n, 當(dāng)偏移量 等于 數(shù)組大小, 說明內(nèi)存全部分配完畢;
-- 偏移量設(shè)計(jì) : 設(shè)置一個(gè)偏移量, 偏移量始終指向大數(shù)組的下一個(gè)空閑的元素地址, 當(dāng)分配內(nèi)存的時(shí)候, 通過計(jì)算 數(shù)組首地址 + 數(shù)組長度 - 偏移量 >= 分配大小 , 成立的話就可以分配內(nèi)存, 分配內(nèi)存就是將偏移量 加上 分配大小; 釋放內(nèi)存的時(shí)候, 就將偏移量 指向 釋放內(nèi)存的指針的首地址, 因此 要保持后進(jìn)先出的次序;
代碼 :?
/*************************************************************************> File Name: alloc_afree.c> Author: octopus> Mail: octopus_work.163.com > Created Time: 2014年03月17日 星期一 19時(shí)34分08秒************************************************************************/#include<stdio.h>//用于內(nèi)存分配載體的大數(shù)組大小 #define ALLOCSIZE 1000 /** 該數(shù)組就是用于內(nèi)存分配的主體, * 設(shè)置為static , 意味著只能在本文件中訪問, 在其它文件中不能訪問*/ static char alloc_buf[ALLOCSIZE]; /** 將alloc_buf 數(shù)組的首地址賦值給allocp字符指針* 對allocp 進(jìn)行算數(shù)運(yùn)算, 每次加減都是 char * 運(yùn)算數(shù)* allocp的值就可以代表所分配內(nèi)存的首地址*/ static char *allocp = alloc_buf;/** 分配n個(gè)char類型數(shù)組的內(nèi)存, * 如果分配成功, 返回分配的內(nèi)存的指針,* 如果分配失敗, 返回0*/ char *alloc(int n) {//如果大數(shù)組剩余的空間可以分配, 那么就進(jìn)行分配if(alloc_buf + ALLOCSIZE - allocp >= n){//分配空間, allocp 指向下一個(gè)空間的內(nèi)存首地址allocp += n;//返回分配的空間首地址return allocp - n;}else //如果數(shù)組剩余空間不足, 返回0{return 0;} }/** 釋放分配的內(nèi)存* 釋放內(nèi)存就是將allocp 指針地址指向 要釋放的內(nèi)存指針首地址*/ void afree(char *p) {//釋放內(nèi)存的前提是 內(nèi)存必須是大于數(shù)組首地址, 小于數(shù)組尾地址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;//打印數(shù)組首地址printf("alloc_buf = %p \n", alloc_buf);//分配300個(gè)字符內(nèi)存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);//上面已經(jīng)分配了900了, 在分配就溢出了, 這里alloc()函數(shù)返回0p4 = alloc(300);printf("char *p4 = alloc(300), p4 = %p \n", p4);afree(p4);afree(p3);afree(p2);afree(p1); }
執(zhí)行結(jié)果 :
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
函數(shù)執(zhí)行示例圖 :?
-- alloc()函數(shù)示例圖 :?
-- afree()函數(shù)示例圖 :?
指針初始化 : static char *allocp = alloc_buf, 將char數(shù)組的首地址賦值給char類型指針;
-- 初始化內(nèi)容 : 0 或者 地址;
-- 地址限定 : 對指針初始化的地址, 該地址存儲的數(shù)據(jù)的類型必須是該指針類型;?
內(nèi)存可用判斷 : alloc_buf + ALLOCSIZE - allocp >= n;
-- 意義 : alloc_buf 是數(shù)組首地址, ALLOCSIZE 是數(shù)組大小, allocp是可用內(nèi)存偏移量, alloc_buf + ALLOCSIZE -allocp 結(jié)果是可用的內(nèi)存量, 如果可用內(nèi)存大于n, 則可以賦值;
-- 如果內(nèi)存不足 : 內(nèi)存不足, 將0作為地址返回, C語言中設(shè)定 0 不是有效的數(shù)據(jù)地址, 0地址的數(shù)據(jù)為NULL, 返回0表示發(fā)生了異常事件;
指針整數(shù)轉(zhuǎn)換特例 : 指針 和 整數(shù) 不能相互轉(zhuǎn)換;
-- 通常情況 : 指針 和 整型 之間不能相互轉(zhuǎn)換, 0 除外;
-- 特例 : 常量 0 可以賦值給指針, 指針 可以和 常量 0 進(jìn)行比較, 這里注意是常量;
-- 0的特殊性 : NULL 可以代替 常量0, 常量0 是一個(gè)特殊值;
指針運(yùn)算 :?
-- 比較運(yùn)算 : 兩個(gè)指針都指向同一個(gè)數(shù)組中的元素, 那么兩個(gè)指針之間的比較是有意義的, 指向兩個(gè)不同數(shù)組元素的指針之間比較無意義;
-- 加減運(yùn)算 : 指向數(shù)組元素的指針, 進(jìn)行加減運(yùn)算, 地址的計(jì)算按照 運(yùn)算數(shù) * 指針指向元素的大小 進(jìn)行計(jì)算;
計(jì)算字符串長度示例 :?
-- 代碼 :?
/*************************************************************************> File Name: strlen_pointer.c> Author: octopus> Mail: octopus_work.163.com > Created Time: 2014年03月17日 星期一 21時(shí)38分52秒************************************************************************/#include<stdio.h>//計(jì)算字符串長度 int strlen(char *s) {//指針 p 記錄首地址char *p = s;//循環(huán)獲取字符串最后的字符首地址while(*p != '\0')p++;//字符串占用的內(nèi)存地址個(gè)數(shù)return p - s; }int main(int argc, char **argv) {char *c = "fuck you!!";printf("length = %d \n", strlen(c));return 0; }
-- 執(zhí)行效果 :?
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 頭文件中, 表示兩個(gè)指針之間的帶符號的差值;
-- size_t : 該類型定義在 stdio.h 頭文件中, size_t 可以作為 sizeof 返回的無符號整型;
指針運(yùn)算一致性 : 指針運(yùn)算會自動考慮其指向的元素的長度, p 指向一個(gè)類型元素 a, 不管 a 占多少字節(jié), p++ 的下一個(gè)元素都指向下一個(gè) 同類型的元素;
指針之間的有效運(yùn)算 : 除下面幾種合法運(yùn)算之外, 其它運(yùn)算都是非法的, 但不會報(bào)錯(cuò), 會警告;
-- 賦值 : 同類型指針之間的賦值運(yùn)算;
-- 算數(shù) : 指針與整數(shù)的加減運(yùn)算;
-- 0相關(guān) : 指針與0 的賦值運(yùn)算, 比較運(yùn)算;
2. 字符指針與函數(shù)示例
字符串常量 : 字符串常量是一個(gè)字符數(shù)組;
-- 字符串常量界定 : 字符數(shù)組以 '\0' 結(jié)束, 程序通過檢查 NULL 字符找到字符串的結(jié)尾;
-- 長度大于1 : 字符串常量占據(jù)的存儲單元 比 字符的個(gè)數(shù) 多1位, 這一位是 '\0';
常量字符串訪問方式 : 通過指針進(jìn)行訪問, 指針指向常量字符串的第一個(gè)字符, 程序可以通過這個(gè)指針操作字符串常量;
字符串定義方式 :?
-- 數(shù)組 : char array[] = "fuck"; array 存放 fuck 字符串 和 '\0', array 地址是字符串首地址;
-- 指針 : char *c = "fuck"; 將字符串的首地址賦值給指針c, 沒有經(jīng)過字符串復(fù)制;
-- 區(qū)別 : 數(shù)組 - array 指向的地址不能改變, 單個(gè)字符可以修改; 指針 - c 指向字符串常量, 可以被修改指向其它地址, 修改字符串內(nèi)容沒有意義, 這樣會在創(chuàng)建一個(gè)字符串常量, 并將首地址賦值給指針;
示例代碼 : 分別用數(shù)組 和 指針 用法 拷貝字符串, 字符串比較;
/*************************************************************************> 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], 每次循環(huán) i++ * 當(dāng)density[i] == '\0'的時(shí)候停止循環(huán)*/ void strcpy_array(char *density, char *source) {int i = 0;while((density[i] = source[i]) != '\0')i++; } /** 字符串拷貝* *density++ 是對*density地址指向的值賦值, 然后地址進(jìn)行自增操作* *source++ 是先取出source 指向的地址的值, 然后地址進(jìn)行自增操作*/ void strcpy_pointer(char *density, char *source) {while(*density++ = *source++); }/** s[i] == t[i] 前提下 s[i] = '\0'* 此時(shí) 返回 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); }
運(yùn)行結(jié)果 :?
[root@ip28 pointer]# gcc string.c [root@ip28 pointer]# ./a.out strcmp_array = -239 strcmp_pointer = -239 source = octopus density = octopus
* 和 自增(減) 運(yùn)算 :?
-- *source++ : 上面的該表達(dá)式的意義是 執(zhí)行 自增運(yùn)算之前, source 指針指向的字符, 讀取到該字符之后, 該指針指向的地址 +1;
-- *density++ = *source++ : source指針自增前, 現(xiàn)將其指向的字符 賦值給 density 之前指向的地址的字符, 然后將 source 指針 +1;
-- 入棧 : *p++ = val, 這是標(biāo)準(zhǔn)的入棧操作, 將val壓入棧, 然后指針自增1, 注意, 這里最后一個(gè)棧多加了一個(gè)1, 然后出棧的時(shí)候要先減1 在取值;
-- 出棧 : val = *--p, 這是標(biāo)準(zhǔn)的出棧操作, 現(xiàn)將指針減一, 然后取出指針指向的數(shù)據(jù), 因?yàn)橹羔樋偸侵赶蚴椎刂? 如果我們想要取出某一段的值, 先要將指針指向首地址才可以;
3. 指針數(shù)組 指向指針的指針 示例
案例需求 :?
-- 實(shí)現(xiàn)功能 : 在單個(gè)運(yùn)算中處理長度不一的文本, 處理可變文本行數(shù)據(jù);?
-- 實(shí)際功能 : 從標(biāo)準(zhǔn)輸入流中輸入多個(gè)字符串, 每個(gè)字符串都使用指針指向字符串的首地址, 然后將指針存放到數(shù)組中, 對字符串?dāng)?shù)組進(jìn)行排序, 按照字典順序輸出;?
引入指針數(shù)組 :?
-- 比較操作 : 對兩個(gè)字符串進(jìn)行移動 比較的時(shí)候, 使用 指向它們的指針進(jìn)行操作, 比較的時(shí)候直接使用下標(biāo)逐一對比;?
-- 拷貝操作 : 字符串拷貝的時(shí)候, 直接將指針賦值給另一個(gè)指針即可, 不用在對文本行進(jìn)行操作;
-- 好處 : 消除了移動文本帶來的內(nèi)存管理 和 開銷;
函數(shù)設(shè)計(jì) :?
-- 設(shè)置函數(shù) : 讀取輸入行, 文本排序, 打印文本行, 設(shè)置上面三個(gè)函數(shù), 在 main 函數(shù)中控制函數(shù)執(zhí)行;
-- 聲明函數(shù) : 在文件開始先聲明一下函數(shù), 那么在整個(gè)文件中就可以使用這個(gè)函數(shù)了, 即使函數(shù)定義在 main 函數(shù)的后面, 也可以調(diào)用;
程序要點(diǎn) :?
-- 輸入流讀取字符串 : 在for循環(huán)中獲取字符, 當(dāng)獲取到 EOF 或者 '\n' 的 或者 獲取字符超過數(shù)組大小 的時(shí)候停止獲取, 返回 獲取的字符串 和 個(gè)數(shù);
-- 創(chuàng)建字符指針數(shù)組 : 當(dāng)獲取到的字符串個(gè)數(shù)為0, 停止獲取字符串, 然后統(tǒng)計(jì)字符串個(gè)數(shù), 根據(jù)字符串個(gè)數(shù)分配字符指針數(shù)組大小;
-- 遞歸排序 :?
-- 打印數(shù)組 : 遍歷指針數(shù)組, 將指針指向的字符串打印出來;
C程序代碼 :?
/*************************************************************************> File Name: string_sort.c> Author: octopus> Mail: octopus_work.163.com > Created Time: 2014年03月18日 星期二 12時(shí)33分19秒************************************************************************/#include<stdio.h> #include<string.h>//定義排序的最大文本行數(shù) #define MAXLINES 100//文本行的指針數(shù)組, 該數(shù)組中存放的是 char 類型指針 char *lineptr[MAXLINES];//每行輸入最大文本數(shù) 10 個(gè)字符 #define MAXLEN 100int 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; }/** 從輸入流中接收收據(jù), 最多接收 max 個(gè)字符, 返回讀取到的字符串長度* 注意 : 函數(shù)不能命名為 getline, 與stdio.h 中的 getline 命名沖突*/ int get_line(char *ch, int max, int nlines) {printf("input the %d char sequence : ", nlines);int c, i;/** getchar() 返回值 時(shí) 無符號的 char 類型轉(zhuǎn)換成的 int 類型* 將int 類型數(shù)據(jù) 賦值給 char 類型, 就是截取 int 的最后8位 即一字節(jié)賦給char變量** 循環(huán)的條件 : * 輸入的字符數(shù)不超過 定義的 MAXLEN 10* 獲取的字符不是 EOF 結(jié)束符* 獲取的字符不是 '\n' 回車** 輸入 EOF(Ctrl + D) 或者 回車 這一行的字符串就會輸入完畢*/for(i = 0; i < max - 1 && (c = getchar()) != EOF && c != '\n'; i++)ch[i] = c;//給字符串加上結(jié)尾 '\0'ch[i] = '\0';return i; }//可分配的內(nèi)存共 11000 字節(jié), 最大文本行數(shù) 100, 每行 100字符, 最大不會超過 10000字節(jié) #define ALLOCSIZE 11000 //alloc函數(shù)可分配的內(nèi)存存儲區(qū) static char allocbuf[ALLOCSIZE]; //空間分配的輔助偏移量 static char *allocp = allocbuf;/** 分配內(nèi)存*/ char *alloc(int n) {//判斷剩余內(nèi)存是否足夠if(allocbuf + ALLOCSIZE - allocp >= n){//分配內(nèi)存, 將偏移量指向下一個(gè)空白內(nèi)存allocp += n;//注意返回分配的內(nèi)存的時(shí)候, 需要將指針指向已經(jīng)分配內(nèi)存的首地址return allocp - n;}elsereturn 0; }int readlines(char *lineptr[], int maxlines) {/** len 獲取的字符串的字符個(gè)數(shù), 注意 不包括 '\0', 是真實(shí)的個(gè)數(shù)* nlines 初始值0, 獲取的字符串個(gè)數(shù), 即字符指針數(shù)組的大小* *p alloc()方法分配內(nèi)存的個(gè)數(shù)* line[MAXLEN] 從輸入流中獲取字符串的載體*/int len, nlines;char *p, line[MAXLEN];nlines = 0;/** 不停的從輸入流獲取字符串, 放到 line 數(shù)組中, 獲取的字符最多100個(gè)* 如果獲取的字符個(gè)數(shù)大于0, 就執(zhí)行循環(huán)體內(nèi)的方法*/while((len = get_line(line, MAXLEN, nlines)) > 0)/** 如果獲取的字符串個(gè)數(shù) 超過 MAXLINES 100 個(gè), 就返回 -1* 如果沒有獲取到足夠的內(nèi)存, 就返回 -1* 分配的內(nèi)存要多分配1個(gè), get_line 返回的函數(shù)小于*/if(nlines >= MAXLINES || (p = alloc(len + 1)) == NULL)return -1;else{//拷貝獲取的字符串 到 alloc 分配的內(nèi)存中strcpy(p, line);//將 alloc 分配的內(nèi)存 指針 放入 指針數(shù)組中l(wèi)ineptr[nlines++] = p;}return nlines; }/** 輸出指針數(shù)組 中 的指針 指向的字符串* 每個(gè)指針都指向一個(gè)字符串?dāng)?shù)組, 不是常量*/ void writelines(char *lineptr[], int nlines) {int i;printf("\n");//便利指針數(shù)組, 將每個(gè)指針代表的字符串打印出來for(i = 0; i < nlines; i++)printf("lineptr[%d] = %s\n", i, lineptr[i]); }//數(shù)組中的兩個(gè)元素進(jìn)行交換 void swap(char *v[], int i, int j) {//每個(gè)數(shù)組元素都是 char * 類型的, 使用 temp 保存數(shù)組元素char *temp;//都是 char * 之間的數(shù)據(jù)進(jìn)行賦值運(yùn)算temp = v[i];v[i] = v[j];v[j] = temp; }/** 參數(shù)解析 : * char *v[] : 字符指針數(shù)組* int left : 排序的字符數(shù)組起始下標(biāo)* int right : 排序的字符數(shù)組的終止下標(biāo)* qsort(array, 0, 3) 將 array 中的 第0個(gè) 到 第3個(gè) 之間的字符串排序*** strcmp(s1, s2)函數(shù)解析 :* 返回值 <0 : s1 < s2* 返回值 =0 : s1 = s2* 返回值 >0 : s1 > s2*/ void qsort(char *v[], int left, int right) {int i, last;//如果數(shù)組的元素個(gè)數(shù)小于2個(gè), 返回if(left >= right)return;//交換最左邊 和 中間元素swap(v, left, (left + right) / 2);//last 記錄last = left;/** 過程解析 : last 指向第一個(gè)元素* 從第二個(gè)元素開始遍歷整個(gè)數(shù)組, 直到遍歷結(jié)束* 如果遍歷的i元素 小于 left 元素* 將last下標(biāo)自增, 然后 與 i 位置互換** 最終 除了 left 之外, 右邊的last 個(gè)都比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);//遞歸進(jìn)行 left 到 中間 的排序qsort(v, left, last - 1);//遞歸進(jìn)行 中間 到 right 的排序qsort(v, last + 1, right); }
運(yùn)行效果 :?
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. 多維數(shù)組案例
日期轉(zhuǎn)程序需求 : 將某月 某日 轉(zhuǎn)換成 一年中的 第多少天, 反之 將某天轉(zhuǎn)換成 某年的 某月某日;
-- 月日轉(zhuǎn)天 : 如 5月1日 是某一年的第幾天, 注 閏年 與 非閏年不同;
-- 天轉(zhuǎn)月日 : 將天數(shù) 轉(zhuǎn)換成 某一年的 月份 和 日期, 注意閏年;
C程序 :?
/*************************************************************************> File Name: multi_array.c> Author: octopus> Mail: octopus_work.163.com > Created Time: 2014年03月18日 星期二 20時(shí)55分07秒************************************************************************/#include<stdio.h>/** 該二維數(shù)組中存放的是 閏年 和 非閏年 每個(gè)月的天數(shù)* day_table[1] 中存放的是 非閏年 每個(gè)月的天數(shù)* day_table[2] 中存放的時(shí) 閏年 每個(gè)月的天數(shù)*/ 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); }/** 遍歷每月的月份數(shù), 將每月的天數(shù)累加 加上 日的天數(shù)* 得出的結(jié)果就是 某日期 在某年的天數(shù)*/ 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; }/** 計(jì)算 某年的天數(shù) 是具體的 幾月幾日* 從 1 開始遍歷二維數(shù)組的 某一年的月份天數(shù)* 如果 天數(shù) 大于 月份天數(shù), 那么 年天數(shù) 減去 月份天數(shù), 然后月份自增* 一直循環(huán)到 年天數(shù) 小于 月份天數(shù)* 那么此時(shí)循環(huán) 月份自增的變量就是月份數(shù), 剩余的 年天數(shù)就是 日* */ 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) {/** 注意指針使用之前一定要初始化, 如果指針不初始化, 就不能使用* 沒有初始化的指針, 不能作為函數(shù)的參數(shù)*/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; }
執(zhí)行結(jié)果 :?
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
二維數(shù)組作參數(shù) : 必須聲明 列數(shù), 行數(shù)可以不進(jìn)行聲明;?
-- 函數(shù)調(diào)用二維數(shù)組本質(zhì) : 函數(shù)調(diào)用的傳遞的是指針, 指針指向一個(gè)數(shù)組, 這個(gè)數(shù)組存放的是指針元素, 每個(gè)指針都指向一個(gè)一維數(shù)組;
-- 必須知道一維數(shù)組大小 : 傳入的只是一個(gè)指針, 如何找到數(shù)組中的第二個(gè)指針呢, 就需要知道一維數(shù)組的大小, 傳入的指針 加上 一維數(shù)組地址 就是 第二個(gè)指針的大小, 如果沒有一維數(shù)組大小, 那么就找不到其它的指針了;
二維數(shù)組參數(shù)正確聲明 :?
-- 帶所有的參數(shù) : fun(int day_table[2][13]);
-- 帶列數(shù), 不帶行數(shù) : fun(int day_table[][13]);
-- 指針參數(shù) : fun(int (*day_table)[13]) , 代表參數(shù)是一個(gè)指針, 這個(gè)指針指向一個(gè) 由 13個(gè)元素組成的一維數(shù)組;
-- 錯(cuò)誤情況 : fun(int *dat_table[13]) 傳入的時(shí)一個(gè) 存放有 13個(gè)指針元素的 一維數(shù)組;
-- 錯(cuò)誤情況 : fun(int day_table[2][]) 沒有列數(shù), 傳入的時(shí)候只傳入了首地址, 無法找到第二個(gè)指針;
5. 指針數(shù)組初始化
示例代碼 :?
/*************************************************************************> 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) {/** 初始化指針數(shù)組, 指針數(shù)組中的元素指向一個(gè)字符串*/static char *name[] = {"Illegal month", "January", "Febrary", "March","April", "May", "June","July", "August", "September","October", "November", "December"};//返回一個(gè)指針, 這個(gè)指針指向字符串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; }
執(zhí)行結(jié)果 :?
[root@ip28 pointer]# gcc montn_name.c [root@ip28 pointer]# ./a.out month 2 is Febrary
指針數(shù)組初始化 : char *name[] 是一個(gè)指針數(shù)組, 這是一個(gè)一維數(shù)組;
-- 指針賦值 : 字符串常量 代表一個(gè)指向該常量首地址的指針, 可以將字符串常量賦值給上面的 一維指針數(shù)組;
6. 區(qū)分指針數(shù)組 與 二維數(shù)組
舉例 :?
int array[2][5];
int *arrayp[2];
二維數(shù)組 : 上面的 array[2][5] 是二維數(shù)組;
-- 空間分配 : 分配了 2 * 5 * sizeof(int) 大小的內(nèi)存空間;
-- 計(jì)算元素地址 : 5 * row + col 是 array[row][col]的地址;
指針數(shù)組 : *array[2] 是指針數(shù)組;
-- 空間分配 : 分配了10個(gè)指針, 沒有對指針進(jìn)行初始化, 必須進(jìn)行手動初始化, 指針指向的一維數(shù)組長度可變, 不固定;
-- 作用 : 指針數(shù)組最主要的作用是存放不同長度的字符串;
指針數(shù)組示例程序 :
/*************************************************************************> 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) {/** 初始化指針數(shù)組, 指針數(shù)組中的元素指向一個(gè)字符串*/static char *name[] = {"Illegal month", "January", "Febrary", "March","April", "May", "June","July", "August", "September","October", "November", "December"};printf("sizeof(name) = %d \n", sizeof(name));//返回一個(gè)指針, 這個(gè)指針指向字符串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; }
執(zhí)行結(jié)果 :?
[root@ip28 pointer]# gcc montn_name.c [root@ip28 pointer]# ./a.out sizeof(name) = 104 month 2 is Febrary
二維數(shù)組示例程序 :?
/*************************************************************************> 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) {/** 初始化指針數(shù)組, 指針數(shù)組中的元素指向一個(gè)字符串*/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));//返回一個(gè)指針, 這個(gè)指針指向字符串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; }
執(zhí)行結(jié)果 :?
[root@ip28 pointer]# gcc month_array.c [root@ip28 pointer]# ./a.out sizeof(name) = 260 month 2 is Febrary
對比 : 二維數(shù)組 占用了 260 字節(jié)內(nèi)存, 指針數(shù)組占用了 104字節(jié)的內(nèi)存; ?
.
作者?:?萬境絕塵
轉(zhuǎn)載請注明出處?:?http://blog.csdn.net/shulianghan/article/details/21402047
.?
總結(jié)
以上是生活随笔為你收集整理的【嵌入式开发】C语言 指针数组 多维数组的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【嵌入式开发】C语言 内存分配 地址
- 下一篇: 【嵌入式开发】C语言 命令行参数 函数指