【嵌入式开发】C语言 内存分配 地址 指针 数组 参数 实例解析
.
Android源碼看的鴨梨大啊, 補一下C語言基礎(chǔ) ...?
.
作者 : 萬境絕塵
轉(zhuǎn)載請注明出處 :?http://blog.csdn.net/shulianghan/article/details/20472269
.
指針簡介 : 指針式保存變量地址的變量;
-- 增加閱讀難度 : 指針 和 goto 語句會增加程序的理解難度, 容易出現(xiàn)錯誤;
-- ANSI C : American National Standards Institute 美國國家標準學(xué)會, 即標準C;
-- 通用指針類型 : ANSI C中使用 void* 作為通用指針類型, 即指向void的指針, void 是空類型, void* 是空類型指針, 可以指向任意類型的地址;
1. void 與 void*?
(1) void 簡介
void 作用 :?
-- 限定參數(shù) : 函數(shù)沒有返回值, 需要使用 void 聲明, 否則默認返回 int 類型;
-- 限定返回值 : 函數(shù)不接收參數(shù), 使用 void 作為參數(shù), 如果傳入?yún)?shù), 編譯器就會報錯;
使用void注意點 :?
-- void不能表示變量 : void a, 這樣定義是錯誤的;
-- 默認返回值 : C 中, 如果沒有標明返回值類型, 默認的返回值不是 void, 是 int 類型;
-- void參數(shù) : C 語言中參數(shù)是void, 傳入?yún)?shù)不會出錯, C++中傳入?yún)?shù)會出錯, 因此這里我們統(tǒng)一規(guī)定, 如果函數(shù)沒有參數(shù), 就定義為void;
.
(2) void*簡介
void * 作用 :?
-- 通用數(shù)據(jù)類型 : void * 指針可以存放任意類型數(shù)據(jù)的地址, 任何數(shù)據(jù)類型的指針都可以賦值給 void * 通用類型指針;
-- 任意類型 : 如果 函數(shù) 的 參數(shù) 和 返回值 可以是任意類型, 就可以使用 void * 作為函數(shù)的 參數(shù) 或者 返回值;
使用void* 注意點 :?
-- void * 與 其它類型互相賦值 : int * 變量可以賦值給 void * 變量, 但是void * 變量如果賦值給 int * 變量需要強轉(zhuǎn)為 int * 類型;
-- void * 不允許進行 算數(shù)操作 : 標準C 中規(guī)定 void * 類型不允許進行 加減乘除 算數(shù)運算, 因為我們不知道這個類型的大小, GUN 中void * 等價于 char * ;
2. C 語言 程序內(nèi)存分配
(1) 內(nèi)存分區(qū)狀況
棧區(qū) (stack) :?
-- 分配, 釋放方式 : 由編譯器自動分配 和 釋放;
-- 存放內(nèi)容 : 局部變量, 參數(shù);
-- 特點 : 具有 后進先出 特性, 適合用于 保存 回復(fù) 現(xiàn)場;
堆區(qū) (heap) :?
-- 分配, 釋放方式 : 由程序員手動 分配(malloc) 和 釋放(free), 如果程序員沒有釋放, 那么程序退出的時候, 會自動釋放;
-- 存放內(nèi)容 : 存放程序運行中 動態(tài)分配 內(nèi)存的數(shù)據(jù);
-- 特點 : 大小不固定, 可能會動態(tài)的 放大 或 縮小;
堆區(qū)內(nèi)存申請?:?
-- 申請過程 : OS中有一個記錄空閑內(nèi)存地址的鏈表, 如果程序員申請內(nèi)存, 就會找到空間大于申請內(nèi)存大小的節(jié)點, 將該節(jié)點從空間內(nèi)存鏈表中刪除, 并分配該節(jié)點;?
-- 剩余內(nèi)存處理 : 系統(tǒng)會將多余的部分重新放回 空閑內(nèi)存鏈表中;
-- 首地址記錄大小 : 分配內(nèi)存的首地址存放該堆的大小, 這樣釋放內(nèi)存的時候才能正確執(zhí)行;?
全局區(qū)/靜態(tài)區(qū) (數(shù)據(jù)段 data segment / bss segment) :?
-- 分配, 釋放方式 : 編譯器分配內(nèi)存, 程序退出時系統(tǒng)自動釋放內(nèi)存;
-- 存放內(nèi)容 : 全局變量, 靜態(tài)變量;
-- 特點 : 全局變量 和 靜態(tài)變量存儲在一個區(qū)域, 初始化的兩種變量 和 未初始化的 存儲在不同區(qū)域, 但是兩個區(qū)域是相鄰的;
常量區(qū)?:?
--?分配, 釋放方式?: 退出程序由系統(tǒng)自動釋放;
--?存放內(nèi)容?: 常量;
代碼區(qū) (text segment) :?
-- 分配, 釋放方式 : 編譯器分配內(nèi)存, 程序退出時系統(tǒng)自動釋放內(nèi)存;
-- 存放內(nèi)容 : 存放 程序的二進制代碼, 和一些特殊常量;
內(nèi)存存放順序 (由上到下) : 棧區(qū) -> 堆區(qū) -> 全局區(qū) -> 常量區(qū) -> 代碼區(qū);
(2) 內(nèi)存分配方式
全局內(nèi)存分配 :?
-- 生命周期 : 編譯時分配內(nèi)存, 程序退出后釋放內(nèi)存, 與 程序 的生命周期相同;
-- 存儲內(nèi)容 : 全局變量, 靜態(tài)變量;
棧內(nèi)存分配 :
-- 生命周期 : 函數(shù)執(zhí)行時分配內(nèi)存, 執(zhí)行結(jié)束后釋放內(nèi)存;
-- 特點 : 該分配運算由處理器處理, 效率高, 但是棧內(nèi)存控件有限;
堆內(nèi)存分配 :?
-- 生命周期 : 調(diào)用 malloc()開始分配, 調(diào)用 free()釋放內(nèi)存, 完全由程序員控制;
-- 謹慎使用 : 如果分配了 沒有釋放, 會造成內(nèi)存泄露, 如果頻繁 分配 釋放 會出現(xiàn)內(nèi)存碎片;?
(3) register變量
使用場景 : 如果 一個變量使用頻率特別高, 可以將這個變量放在 CPU 的寄存器中;
-- 修飾限制 : 只有 局部變量 和 參數(shù) 可以被聲明為 register變量, 全局 和 靜態(tài)的不可以;
-- 數(shù)量限制 : CPU 寄存器 很寶貴, 不能定義太多register變量;
(4) extern 變量
extern變量概念 : 聲明外部變量, 外部變量就是在函數(shù)的外部定義的變量, 在本函數(shù)中使用;
-- 作用域 : 從外部變量定義的位置開始, 知道本源碼結(jié)束都可以使用, 但是只能在定義extern后面使用, 前面的代碼不能使用;
-- 存放位置 : 外部變量 存放在 全局區(qū);
extern變量作用 : 使用extern修飾外部變量, ① 擴展外部變量在本文件中的作用域, ② 將外部變量作用域從一個文件中擴展到工程中的其它文件;
extern聲明外部變量的情況 :?
-- 單個文件內(nèi)聲明 : 如果不定義在文件開頭, 其作用范圍只能是 定義位置開始, 文件結(jié)束位置結(jié)束;
-- 多個文件中聲明 : 兩個文件中用到一個外部變量, 只能定義一次, 編譯 和 連接的時候, 如果沒有這個外部變量, 系統(tǒng)會知道這個外部變量在別處定義, 將另一個文件中的外部變量擴展到本文件中;
extern編譯原則 :?
-- 本文件中能找到 : 編譯器遇到 extern 的時候, 現(xiàn)在本文件中找外部變量的定義的位置, 如果找到, 就將作用域擴展到 定義的位置 知道文件結(jié)束;
-- 本文件中找不到 : 如果本文件中找不到, 連接其它文件找外部變量定義, 如果找到, 將外部變量作用域擴展到本文件中;
-- 外部文件找不到 : 報錯;
使用效果 : extern 使用的時候, 可以不帶數(shù)據(jù)類型;
-- 本文件 : int A = 0; 在第10行, extern A 在第一行, 那么A的作用域就擴展為從第一行到文件末尾;
-- 多文件 : 在任意文件中定義了 int A = 0; 在本文件中聲明 extern A, 那么從當(dāng)前位置到文件末尾都可以使用該變量;
(5) static變量 與 全局變量區(qū)別
static 變量 與 全局變量 相同點 : 全局變量是靜態(tài)存儲的, 存儲的方式 和 位置基本相同;
static 變量 與 全局變量不用點 : 全局變量的作用域是 整個項目工程 橫跨過個文件, 靜態(tài)變量的作用域是 當(dāng)前文件, 其它文件中使用是無效的;
變量存儲位置 : 全局變量 和 靜態(tài)變量 存放在 全局區(qū)/靜態(tài)去, 局部變量存放在 棧區(qū)(普通變量, 指針變量內(nèi)容) 和 堆區(qū)(指針變量指向的內(nèi)容);
變量靜態(tài)化 :?
-- 局部變量 : 局部變量 加上 static , 相當(dāng)于將局部變量的生命周期擴大到了整個文件, 作用域不改變;
-- 全局變量 : 全局變量 加上 static , 相當(dāng)于將全局變量的作用域縮小到了單個文件, 生命周期是整個程序的周期;
關(guān)于函數(shù)頭文件的引申 :?
-- 內(nèi)部函數(shù) : 單個文件中使用的內(nèi)部函數(shù), 僅在那個特定文件中定義函數(shù)即可;
-- 全局函數(shù) : 如果要在整個工程中使用一個全局函數(shù), 需要將這個函數(shù)定義在一個頭文件中;
static變量與普通變量區(qū)別 :?
-- static全局變量 與 全局變量區(qū)別 : static 全局變量 只初始化一次, 防止在其它文件中使用;
-- static局部變量 與 局部變量區(qū)別 : static 局部變量 只初始化一次, 下一次依據(jù)上一次結(jié)果;
static函數(shù)與普通函數(shù)區(qū)別 : static 函數(shù)在內(nèi)存中只保留一份, 普通函數(shù) 每調(diào)用一次, 就創(chuàng)建一個副本;
.
(6) 堆 和 棧比較
堆(heap)和棧(stack)區(qū)別 :?
-- 申請方式 : stack 由系統(tǒng)自動分配, heap 由程序員進行分配;
-- 申請響應(yīng) : 如果 stack 沒有足夠的剩余空間, 就會溢出; 堆內(nèi)存從鏈表中找空閑內(nèi)存;
-- 內(nèi)存限制 : stack 內(nèi)存是連續(xù)的, 從高位向低位擴展, 而且很小, 只有幾M, 是事先定好的, 在文件中配置; heap 是不連續(xù)的, 從低位向高位擴展, 系統(tǒng)是由鏈表控制空閑程序, 鏈表從低地址到高地址, 堆大小受虛擬內(nèi)存限制, 一般32位機器有4G heap;
-- 申請效率 : stack 由系統(tǒng)分配, 效率高; heap 由程序員分配, 速度慢, 容易產(chǎn)生碎片;
(7) 各區(qū)分布情況
.
按照下圖分布 : 由上到下順序 : 棧區(qū)(stack) -> 堆區(qū)(heap) -> 全局區(qū) -> 字符常量區(qū) -> 代碼區(qū);
驗證分區(qū)狀況 :?
-- 示例程序 :?
/*************************************************************************> File Name: memory.c> Author: octopus> Mail: octopus_work.163.com > Created Time: Mon 10 Mar 2014 08:34:12 PM CST************************************************************************/#include<stdio.h> #include<stdlib.h>int global1 = 0, global2 = 0, global3 = 0;void function(void) {int local4 = 0, local5 = 0, local6 = 0;static int static4 = 0, static5 = 0, static6 = 0;int *p2 = (int*)malloc(sizeof(int));printf("子函數(shù) 局部變量 : \n");printf("local4 : %p \n", &local4);printf("local5 : %p \n", &local5);printf("local6 : %p \n", &local6);printf("子函數(shù) 指針變量 : \n");printf("p2 : %p \n", p2);printf("全局變量 : \n");printf("global1 : %p \n", &global1);printf("global2 : %p \n", &global2);printf("global3 : %p \n", &global3);printf("子函數(shù) 靜態(tài)變量 : \n");printf("static4 : %p \n", &static4);printf("static5 : %p \n", &static5);printf("static6 : %p \n", &static6);printf("子函數(shù)地址 : \n");printf("function : %p \n", function); }int main(int argc, char **argv) {int local1 = 0, local2 = 0, local3 = 0;static int static1 = 0, static2 = 0, static3 = 0;int *p1 = (int*)malloc(sizeof(int));const int const1 = 0;char *char_p = "char";printf("主函數(shù) 局部變量 : \n");printf("local1 : %p \n", &local1);printf("local2 : %p \n", &local2);printf("local3 : %p \n", &local3);printf("const1 : %p \n", &const1);printf("主函數(shù) 指針變量 : \n");printf("p1 : %p \n", p1);printf("全局變量 : \n");printf("global1 : %p \n", &global1);printf("global2 : %p \n", &global2);printf("global3 : %p \n", &global3);printf("主函數(shù) 靜態(tài)變量 : \n");printf("static1 : %p \n", &static1);printf("static2 : %p \n", &static2);printf("static3 : %p \n", &static3);printf("字符串常量 : \n");printf("char_p : %p \n", char_p);printf("主函數(shù)地址 : \n");printf("main : %p \n", main);printf("= = = = = = = = = = = = = = = \n");function();return 0; }
-- 執(zhí)行結(jié)果 :?
[root@ip28 pointer]# gcc memory.c [root@ip28 pointer]# ./a.out 主函數(shù) 局部變量 : local1 : 0x7fff75f5eedc local2 : 0x7fff75f5eed8 local3 : 0x7fff75f5eed4 const1 : 0x7fff75f5eed0 主函數(shù) 指針變量 : p1 : 0x19bad010 全局變量 : global1 : 0x600e14 global2 : 0x600e18 global3 : 0x600e1c 主函數(shù) 靜態(tài)變量 : static1 : 0x600e34 static2 : 0x600e30 static3 : 0x600e2c 字符串常量 : char_p : 0x4009f7 主函數(shù)地址 : main : 0x40065f = = = = = = = = = = = = = = = 子函數(shù) 局部變量 : local4 : 0x7fff75f5eea4 local5 : 0x7fff75f5eea0 local6 : 0x7fff75f5ee9c 子函數(shù) 指針變量 : p2 : 0x19bad030 全局變量 : global1 : 0x600e14 global2 : 0x600e18 global3 : 0x600e1c 子函數(shù) 靜態(tài)變量 : static4 : 0x600e28 static5 : 0x600e24 static6 : 0x600e20 子函數(shù)地址 : function : 0x400528
3. 指針與地址
(1) & 與 * 操作
取地址運算符 & : p = &c;
-- 表達式解析 : 將 c 的地址賦值給 變量 p, p 是指向 c 變量的指針;
-- & 可以使用的情況 : 取地址操作 只能用于內(nèi)存中的對象, 如變量 或 數(shù)組, 棧內(nèi)存 堆內(nèi)存 都可以;
-- & 不適用的情況 : 不能用于 表達式, 常量, register類型變量;?
間接引用運算符 : * ;
-- 聲明指針 : int *p ; 該表達式的含義是 *p 的結(jié)果是 int 類型, 聲明變量 a, int a, 聲明指針 *p , int *p;
-- 獲取指針指向的值 : int a = *p ;
(2) 指針定義解析
聲明指針 和 函數(shù) : int *p, max(int a, int b), 聲明指針變量 語法 與聲明 變量語法類似, 同理聲明函數(shù)也一樣;
-- 原理 : *p 和 max()返回值 類型都是 int 類型;
指針指向 : 每個指針都必須指向某種特定類型;
-- 例外 : void *p 可以指向任何類型, 但是 p 不能進行取值運算, *p 是錯誤的, 因為不知道 p 指向的數(shù)據(jù)類型;
(3) 指針運算及示例
指針相關(guān)運算 : int x = 0; int *p = &x; 那么*p 就可以代表x;
-- 算數(shù)運算 : x = x + 1; 等價于 *p = *p + 1 ; int y = x + 1; 等價于 int y = *p + 1;
-- 自增運算 : 前提 : ++, * 運算順序是自右向左; ?++*p 和 (*p)++, p 指向的值自增1, 注意要加上括號, 否則會將地址自增;
-- 指針賦值 : int *p, *q; int a = 0; p = &a; q = p; 最終結(jié)果 p 和 q 都指向了 變量 a;
示例程序 :?
/*************************************************************************> File Name: pointer_address.c> Author: octopus> Mail: octopus_work.163.com > Created Time: Mon 10 Mar 2014 09:52:01 PM CST************************************************************************/#include<stdio.h>int main(int argc, char ** argv) {int *p, *q;int a = 10, b;//p指針指向a變量p = &a;//*p 可以代替 a 進行運算++*p;b = *p + 5;//指針之間可以直接相互賦值q = p;//打印 p 和 q 指針指向的值printf("*p = %d \n", *p);printf("*q = %d \n", *q);return 0; }
執(zhí)行結(jié)果 :
[root@ip28 pointer]# gcc pointer_address.c [root@ip28 pointer]# ./a.out *p = 11 *q = 11
4. 函數(shù)參數(shù)的傳值調(diào)用和傳址調(diào)用
(1) 傳值調(diào)用 和 傳址調(diào)用
傳值調(diào)用 : 以傳值的方式將參數(shù)傳遞給函數(shù), 不能直接修改主函數(shù)中變量的值, 僅僅是將副本傳遞給了函數(shù);
傳址調(diào)用 : 將 變量的指針 傳遞給函數(shù), 當(dāng)函數(shù)對指針進行操作的時候, 主函數(shù)中的值也進行了對應(yīng)變化;
交換函數(shù)示例1?:?
/*************************************************************************> File Name: swap.c> Author: octopus> Mail: octopus_work.163.com > Created Time: Mon 10 Mar 2014 11:07:18 PM CST************************************************************************/#include<stdio.h>void swap_1(int a, int b) {int temp;temp = a;a = b;b = temp;printf("swap_1 傳值 函數(shù) a = %d, b = %d \n", a, b); }void swap_2(int *a, int *b) {int temp;temp = *a;*a = *b;*b = temp;printf("swap_2 傳址 函數(shù) a = %d, b = %d\n", *a, *b); }int main(int argc, char **argv) {int a = 10, b = 5;printf("初始值 : a = %d, b = %d \n\n", a, b);swap_1(a, b);printf("執(zhí)行 swap_1 函數(shù), a = %d, b = %d \n\n", a, b);swap_2(&a, &b);printf("執(zhí)行 swap_2 函數(shù), a = %d, b = %d \n", a, b);return 0; }執(zhí)行結(jié)果 :?
[root@ip28 pointer]# gcc swap.c [root@ip28 pointer]# ./a.out 初始值 : a = 10, b = 5 swap_1 傳值 函數(shù) a = 5, b = 10 執(zhí)行 swap_1 函數(shù), a = 10, b = 5 swap_2 傳址 函數(shù) a = 5, b = 10 執(zhí)行 swap_2 函數(shù), a = 5, b = 10
示例解析 :?
-- 傳值調(diào)用 : swap_1 是傳值調(diào)用, 傳入的是 main 函數(shù)中的 a b 兩個變量的副本, 因此函數(shù)執(zhí)行完畢后, 主函數(shù)中的值是不變的;
-- 傳址調(diào)用 : swap_2 是傳址調(diào)用, 傳入的是 a , b 兩個變量的地址 &a, &b, 當(dāng)在swap_2 中進行修改的時候, 主函數(shù)中的 a,b變量也會發(fā)生改變;
(2) 高級示例
需求分析 : 調(diào)用getint()函數(shù), 將輸入的數(shù)字字符 轉(zhuǎn)為一個整形數(shù)據(jù);
getch 和 ungetch 函數(shù) :?
-- 使用場景 : 當(dāng)進行輸入的時候, 不能確定是否已經(jīng)輸入足夠的字符, 需要讀取下一個字符, 進行判斷, 如果多讀取了一個字符, 就需要將這個字符退回去;
-- 使用效果 : getch() 和 ungetch() 分別是預(yù)讀下一個字符, 和 將預(yù)讀的字符退回去, 這樣對于其它代碼而言, 沒有任何影響;
注意的問題 : 出現(xiàn)問題, 暫時編譯不通過, 找個C語言大神解決;
代碼 :?
/*************************************************************************> File Name: getint.c> Author: octopus> Mail: octopus_work.163.com > Created Time: Mon 10 Mar 2014 11:40:19 PM CST************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define SIZE 5int getint(int *p) {//sign 是用來控制數(shù)字的正負int c, sign;//跳過空白字符, 如果是空白字符, 就會進行下一次循環(huán), 直到不是空白字符為止while(isspace(c = getc(stdin)));//如果輸入的字符不是數(shù)字, 就將預(yù)讀的數(shù)據(jù)退回到標準輸入流中if(!isdigit(c) && c != EOF && c != '+' && c != '-'){ungetc(c, stdin);return 0;}/** 如果預(yù)讀的是減號, 那么sign 標識就是 -1, * 如果預(yù)讀的是加號, 那么sign 標識就是 1;*/sign = (c == '-') ? -1 : 1;//如果 c 是 加號 或者 減號, 再預(yù)讀一個字符&if(c == '+' || c == '-')c = getc(stdin);for(*p = 0; isdigit(c); c = getc(stdin))*p = 10 * *p + (c - '0');*p *= sign;if(c != EOF)ungetc(c, stdin);return c;}int main(int argc, char **argv) {int n, array[SIZE], i; for(n = 0; n < SIZE && getint(&array[n]) != EOF; n++);for(i = 0; i < SIZE; i++){printf("array[%d] = %d \n", i, array[i]);}return 0; }
執(zhí)行結(jié)果 :?
octopus@octopus-Vostro-270s:~/code/c/pointer$ ./a.out 123 123 43 674 1 array[0] = 123 array[1] = 123 array[2] = 43 array[3] = 674 array[4] = 1
5. 指針 和 數(shù)組
指針數(shù)組比較 :?
-- 可互相替代 : 數(shù)組下標執(zhí)行的操作都可以使用指針替代;
-- 效率比較 : 使用指針操作效率比數(shù)組要高;
指針 與 數(shù)組初始化 :?
-- 聲明數(shù)組 : int a[10]; 定義一個長度為10 的int數(shù)組;
-- 聲明指針 : int *p; 定義一個指針, 該指針指向整型;
-- 相互賦值 : p = &a[0], 將數(shù)組第一個元素的地址賦值給指針變量;
-- 使用指針獲取數(shù)組對象 : *p 等價于 a[0], *(p + 1) 等價于 a[1], *(p + i)等價于 a[i];
-- 注意地址的運算 : p + i , 在地址運算上, 每次增加 sizeof(int) * i 個字節(jié);
將數(shù)組賦值給指針的途徑 :?
-- 將數(shù)組第一個元素地址賦值給指針變量 : p = &a[0];
-- 將數(shù)組地址賦值給指針變量 : p = a;
指針 和 數(shù)組 訪問方式互換 : 前提 int *p, a[10]; p = a;
-- 數(shù)組計算方式 : 計算a[i]的時候, 先將數(shù)組轉(zhuǎn)化為 *(a + i)指針, 然后計算該指針值;
-- 取值等價 : a[i] 等價于 *(p + i);
-- 地址等價 : &a[i] 與 a + i 是等價的;
-- 指針下標訪問 : p[i] 等價于 *(p + i);
-- 結(jié)論 : 通過數(shù)組和下標 實現(xiàn)的操作 都可以使用 指針和偏移量進行等價替換;
指針 和 數(shù)組 的不同點 :?
-- 指針是變量 : int *p, a[10]; p = a 和 p++ 沒有錯誤;
-- 數(shù)組名不是變量 : int *p, a[10]; a = p 和 a++ 會報錯;
數(shù)組參數(shù) :?
-- 形參指針 : 將數(shù)組傳作為參數(shù)傳遞給函數(shù)的時候, 傳遞的是數(shù)組的首地址, 傳遞地址, 形參是指針;
數(shù)組參數(shù)示例 :?
-- 函數(shù)參數(shù)是數(shù)組 : 函數(shù)傳入一個字符串?dāng)?shù)組參數(shù), 返回這個字符串長度;
/*************************************************************************> File Name: array_param.c> Author: octopus> Mail: octopus_work.163.com > Created Time: Sat 15 Mar 2014 12:46:57 AM CST************************************************************************/#include<stdio.h>//計算字符串長度 int strlen(char *s) {int n;for(n = 0; *s != '\0'; s++)n++;return n; }int main(int argc, char** argv) {printf("strlen(djdhaj) = %d \n", strlen("djdhaj"));printf("strlen(12) = %d \n", strlen("12"));printf("strlen(dfe) = %d \n", strlen("dfe")); }
-- 執(zhí)行結(jié)果 :?warning: conflicting types for built-in function ‘strlen’, 原因是 C語言中已經(jīng)有了 strlen 函數(shù)了, 如果改一個函數(shù)名, 就不會有這個警告了;
[root@ip28 pointer]# gcc array_param.c array_param.c:12: warning: conflicting types for built-in function ‘strlen’ [root@ip28 pointer]# ./a.out strlen(djdhaj) = 6 strlen(12) = 2 strlen(dfe) = 3
數(shù)組和指針參數(shù) :?將數(shù)組名傳給參數(shù), 函數(shù)根據(jù)情況判斷是作為數(shù)組還是作為指針;
-- 實參 : 指針偏移量 和 數(shù)組下標 都可以作為 數(shù)組或指針函數(shù)形參, 如 數(shù)組情況fun(&array[2]) 或者 指針情況fun(p + 2);
-- 形參 : 函數(shù)的形參可以聲明為 fun(int array[]), 或者 fun(int *array), 如果傳入的是數(shù)組的第二個元素的地址, 可以使用array[-2]來獲數(shù)組取第一個元素;
數(shù)組指針參數(shù)示例 :?
/*************************************************************************> File Name: param_array_pointer.c> Author: octopus> Mail: octopus_work.163.com > Created Time: Sat 15 Mar 2014 01:28:33 AM CST************************************************************************/#include<stdio.h>//使用指針做形參 取指針的前兩位 和 當(dāng)前位 void fun_p(int *p) {printf("*(p - 2) = %d \n", *(p - 2));printf("*p = %d \n", *p); }//使用數(shù)組做形參 取數(shù)組的 第-2個元素 和 第0個元素 void fun_a(int p[]) {printf("p[-2] = %d \n", p[-2]);printf("p[0] = %d \n", p[0]); }int main(int argc, char **argv) {int array[] = {1,2,3,4,5};//向指針參數(shù)函數(shù)中傳入指針printf("fun_p(array + 2) : \n");fun_p(array + 2);//向數(shù)組參數(shù)函數(shù)中傳入數(shù)組元素地址printf("fun_a(&array[2]) : \n");fun_a(&array[2]);//向指針參數(shù)函數(shù)中傳入數(shù)組元素地址printf("fun_p(&array[2]) : \n");fun_p(&array[2]);//向數(shù)組參數(shù)函數(shù)中傳入指針printf("fun_a(array + 2) : \n");fun_a(array + 2);return 0; }執(zhí)行效果 :? [root@ip28 pointer]# gcc param_array_pointer.c [root@ip28 pointer]# ./a.out fun_p(array + 2) : *(p - 2) = 1 *p = 3 fun_a(&array[2]) : p[-2] = 1 p[0] = 3 fun_p(&array[2]) : *(p - 2) = 1 *p = 3 fun_a(array + 2) : p[-2] = 1 p[0] = 3
.
作者?:?萬境絕塵
轉(zhuǎn)載請注明出處?:?http://blog.csdn.net/shulianghan/article/details/20472269
.
總結(jié)
以上是生活随笔為你收集整理的【嵌入式开发】C语言 内存分配 地址 指针 数组 参数 实例解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 应用开发】Ubuntu
- 下一篇: 【嵌入式开发】C语言 指针数组 多维数组