【C 语言】C 语言 函数 详解 ( 函数本质 | 顺序点 | 可变参数 | 函数调用 | 函数活动记录 | 函数设计 ) [ C语言核心概念 ]
相關(guān)文章鏈接 :
1.【嵌入式開發(fā)】C語言 指針數(shù)組 多維數(shù)組
2.【嵌入式開發(fā)】C語言 命令行參數(shù) 函數(shù)指針 gdb調(diào)試
3.【嵌入式開發(fā)】C語言 結(jié)構(gòu)體相關(guān) 的 函數(shù) 指針 數(shù)組
4.【嵌入式開發(fā)】gcc 學(xué)習(xí)筆記(一) - 編譯C程序 及 編譯過程
5.【C語言】 C 語言 關(guān)鍵字分析 ( 屬性關(guān)鍵字 | 常量關(guān)鍵字 | 結(jié)構(gòu)體關(guān)鍵字 | 聯(lián)合體關(guān)鍵字 | 枚舉關(guān)鍵字 | 命名關(guān)鍵字 | 雜項(xiàng)關(guān)鍵字)
6.【C 語言】編譯過程 分析 ( 預(yù)處理 | 編譯 | 匯編 | 鏈接 | 宏定義 | 條件編譯 | 編譯器指示字 )
7.【C 語言】指針 與 數(shù)組 ( 指針 | 數(shù)組 | 指針運(yùn)算 | 數(shù)組訪問方式 | 字符串 | 指針數(shù)組 | 數(shù)組指針 | 多維數(shù)組 | 多維指針 | 數(shù)組參數(shù) | 函數(shù)指針 | 復(fù)雜指針解讀)
- 一. 函數(shù)本質(zhì)
- 1. 函數(shù)意義
- (1) 函數(shù)來源
- (2) 模塊化程序設(shè)計(jì)
- 2. 面向過程的程序設(shè)計(jì)
- (1) 程序結(jié)構(gòu)
- 3. 函數(shù)的聲明和定義
- (1) 聲明 和 定義 的區(qū)別
- (2) 代碼示例 ( 函數(shù) 聲明 和 定義區(qū)別 )
- 1. 函數(shù)意義
- 二. 參數(shù) 可變參數(shù) 順序點(diǎn) 類型缺省認(rèn)定
- 1. 函數(shù)參數(shù)
- (1) 參數(shù)分析
- (2) 代碼示例 ( 函數(shù)參數(shù) 求值順序 )
- 2. 程序中的順序點(diǎn)
- (1) 順序點(diǎn)簡介
- 3. C 語言 函數(shù) 的 缺省認(rèn)定
- (n) 標(biāo)題3
- 4.可變參數(shù) 的 定義 和 使用
- (1) 簡介
- (2) 代碼示例 ( 定義 使用 可變參數(shù) )
- 1. 函數(shù)參數(shù)
- 三. 函數(shù) 與 宏
- 1. 函數(shù) 與 宏 對比案例
- (1) 函數(shù) 和 宏 的案例
- 2. 函數(shù) 和 宏 的分析
- (1) 函數(shù) 和 宏 分析
- 3. 函數(shù) 與 宏 的 利弊
- (1) 宏 優(yōu)勢 和 弊端
- (2) 函數(shù) 的 優(yōu)勢 和 弊端
- (3) 宏的無可替代性
- 4. 總結(jié)
- (1) 宏 定義 和 函數(shù) 總結(jié)
- 1. 函數(shù) 與 宏 對比案例
- 四. 函數(shù)的調(diào)用約定
- 1. 函數(shù)的活動記錄 分析
- (1) 函數(shù)的活動記錄
- 2. 函數(shù)的調(diào)用約定概述
- (1) 參數(shù)入棧 問題描述
- (2) 參數(shù)傳遞順序的調(diào)用約定
- 1. 函數(shù)的活動記錄 分析
- 五. 函數(shù)設(shè)計(jì)技巧
一. 函數(shù)本質(zhì)
1. 函數(shù)意義
(1) 函數(shù)來源
C 程序結(jié)構(gòu) 由 數(shù)據(jù) 和 函數(shù) 組成;
函數(shù)是由匯編跳轉(zhuǎn)發(fā)展而來的 :
- 1.匯編操作 : 匯編語言中由一系列的指令組成, 這些指令從上到下順序執(zhí)行,
- 2.跳轉(zhuǎn)操作 : 匯編中需要做分支循環(huán)操作的時(shí)候, 就是使用跳轉(zhuǎn)指令;
- 3.指令代碼模塊 : 在匯編中有一組指令代碼, 總是需要執(zhí)行這一組代碼, 需要時(shí)跳轉(zhuǎn)到該代碼處執(zhí)行, 執(zhí)行完畢后在跳轉(zhuǎn)回去, 這就是一個(gè)函數(shù)的雛形;
- 4.發(fā)展 : 跳轉(zhuǎn)過來 和 跳轉(zhuǎn)回去 相當(dāng)于函數(shù)的 入棧 和 出棧;
(2) 模塊化程序設(shè)計(jì)
模塊化程序設(shè)計(jì) :
- 1.思想 : 復(fù)雜問題拆解, 將一個(gè)復(fù)雜問題拆解成一個(gè)個(gè)的簡單問題, 這些簡單問題就可以作為一個(gè)個(gè)的函數(shù)來編寫;
- 2.C語言程序 : 將一個(gè)復(fù)雜的程序拆解成一個(gè)個(gè)模塊 和 庫函數(shù);
一個(gè)復(fù)雜的 C 語言程序有幾十上百萬行代碼, 這些代碼可以分解成若干模塊來實(shí)現(xiàn), 即分解成一個(gè)個(gè)的函數(shù)來實(shí)現(xiàn).
2. 面向過程的程序設(shè)計(jì)
(1) 程序結(jié)構(gòu)
面向過程程序設(shè)計(jì)思想 :
- 1.中心 : 整體的設(shè)計(jì) 以 過程 為中心;
- 2.問題分解 : 將復(fù)雜問題分解為若干容易解決的問題;
- 3.函數(shù)體現(xiàn) : 面向過程 的思想在 C 語言 中的核心就是 函數(shù);
- 4.分解函數(shù) : 復(fù)雜問題 分解后的過程可以分為一個(gè)個(gè)函數(shù)一步步實(shí)現(xiàn);
3. 函數(shù)的聲明和定義
(1) 聲明 和 定義 的區(qū)別
聲明和定義的區(qū)別 :
- 1.聲明 : 程序中 聲明 只是告訴編譯器 某個(gè) 實(shí)體 存在, 這個(gè)實(shí)體可以是 變量 或者 函數(shù) 等;
- 2.定義 : 程序中定義 指的就是 某個(gè)實(shí)體 ( 函數(shù) 或 變量 ) 的實(shí)際意義;
在 test_1.c 中定義變量 int i = 10; 這是定義了 int 類型的變量, 需要為該變量分配內(nèi)存空間;
在 test_2.c 中聲明變量 extern int i; 這是聲明了 int 類型的變量, 變量定義在了別的文件中, 不必為該變量分配內(nèi)存空間;
(2) 代碼示例 ( 函數(shù) 聲明 和 定義區(qū)別 )
代碼示例 :
- 1.代碼 test_1.c :
- 2.代碼test_2.c :
- 3.編譯運(yùn)行結(jié)果 :
二. 參數(shù) 可變參數(shù) 順序點(diǎn) 類型缺省認(rèn)定
1. 函數(shù)參數(shù)
(1) 參數(shù)分析
函數(shù)參數(shù)分析 :
- 1.本質(zhì) : 函數(shù)參數(shù)的本質(zhì) 與 局部變量 基本相同, 這兩種數(shù)據(jù)都存放在棧空間中 ( 中間隔著 返回地址 寄存器 EBP 數(shù)據(jù) ) 詳情參考上一篇博客內(nèi)存管理 ;
- 2.參數(shù)值 : 函數(shù)調(diào)用的 初始值 是 函數(shù)調(diào)用時(shí)的實(shí)參值 ;
函數(shù)參數(shù)的求值順序 (盲點(diǎn)) :
- 1.實(shí)現(xiàn) : 函數(shù)參數(shù)的求值順序 依賴 編譯器的實(shí)現(xiàn);
- 2.操作數(shù)順序沒有在規(guī)范中 : C 語言規(guī)范中沒有規(guī)定函數(shù)參數(shù)必須從左到右進(jìn)行計(jì)算賦值;
- 3.運(yùn)算符編程注意點(diǎn) : C語言中大多數(shù)的運(yùn)算符的操作數(shù)求值順序也是不固定的, 依賴于編譯器的實(shí)現(xiàn);
- 4.示例 : 如 int ret = fun1() * fun2(); fun1 和 fun2 函數(shù)哪個(gè)先執(zhí)行, 哪個(gè)后執(zhí)行 不一定;
編程時(shí)盡量不要編寫的代碼依賴于操作數(shù)的實(shí)現(xiàn)順序;
(2) 代碼示例 ( 函數(shù)參數(shù) 求值順序 )
代碼示例 :
- 1.代碼 :
- 2.編譯運(yùn)行結(jié)果 :
分析 :
函數(shù)參數(shù)計(jì)算說明 : fun(m, m ++); 進(jìn)入函數(shù)體之前先計(jì)算 m 和 m++ 的值, m 和 m++ 是實(shí)參, 在計(jì)算完成之后才賦值給 i 和 j 形參;
順序點(diǎn) : 在進(jìn)入函數(shù)體前是一個(gè)順序點(diǎn), 需要將計(jì)算完畢的實(shí)參 賦值給形參;
實(shí)參 m 賦值 : 賦值給 形參 i, 此處已經(jīng)到達(dá)順序點(diǎn), m 自增操作已經(jīng)反映到內(nèi)存中, 因此 從 內(nèi)存中獲取的 i 的值是 2;
實(shí)參 m++ 賦值 : 賦值給 形參 j, m++ 表達(dá)式的計(jì)算結(jié)果是 1, 因此 j 的值是1;
2. 程序中的順序點(diǎn)
(1) 順序點(diǎn)簡介
順序點(diǎn)介紹 :
- 1.順序點(diǎn)位置 : 順序點(diǎn)存在于程序之中;
- 2.順序點(diǎn)定義 : 順序點(diǎn)是 代碼 執(zhí)行過程中, 修改變量值 的 最晚時(shí)刻 ;
- 3.順序點(diǎn)操作 : 程序運(yùn)行到順序點(diǎn)時(shí), 之前的代碼操作 都要反映到后續(xù)訪問中 ;
順序點(diǎn)列舉 :
- 1.表達(dá)式結(jié)束 : 每個(gè)表達(dá)式結(jié)束都是順序點(diǎn), 以分號 “;” 結(jié)尾, 每個(gè)分號的位置都是順序點(diǎn);
- 2.某些表達(dá)式的運(yùn)算對象計(jì)算 : &&, || (邏輯運(yùn)算), ? :(三目運(yùn)算符), 逗號 表達(dá)式 中每個(gè) 運(yùn)算對象計(jì)算后 是順序點(diǎn);
- 3.函數(shù)運(yùn)行前 : 函數(shù)調(diào)用并且在執(zhí)行函數(shù)體之前, 所有實(shí)際參數(shù)求值完之后是一個(gè)順序點(diǎn), 如參數(shù)是表達(dá)式, 需要將表達(dá)式計(jì)算出結(jié)果;
順序點(diǎn)代碼示例 :
#include <stdio.h>int fun(int i, int j) {printf("%d, %d\n", i, j); }//注意 : 這個(gè)知識點(diǎn)可能過時(shí), k = k++ + k++; 在 Ubuntu 中執(zhí)行結(jié)果是 5int main() {//順序點(diǎn) : 在 k = 2; 表達(dá)式以分號結(jié)束, 這是一個(gè)順序點(diǎn)int k = 2;int a = 1;/*順序點(diǎn) : 分號結(jié)尾處是順序點(diǎn), 該順序點(diǎn)第 1 個(gè) k++, 計(jì)算時(shí) k 先是 2, 自增操作到順序點(diǎn)時(shí)執(zhí)行; 第 2 個(gè) k++, 計(jì)算時(shí) k 還是 2, 自增操作到順序點(diǎn)時(shí)執(zhí)行;加法計(jì)算完畢后 k 變成 4, 兩次自增后變?yōu)?6*/k = k++ + k++;printf("k = %d\n", k);/*a-- && a 進(jìn)行邏輯運(yùn)算, 其中 && 是順序點(diǎn), a-- 在 && 時(shí)執(zhí)行 自減操作, 然后 a-- 結(jié)果變成了 0, a 的值也變成了 0, 進(jìn)行邏輯與操作結(jié)果為 0 */printf("a--&&a = %d\n",a--&&a);return 0; }
3. C 語言 函數(shù) 的 缺省認(rèn)定
(n) 標(biāo)題3
函數(shù)缺省認(rèn)定簡介 :
- 1.描述 : C 語言中 默認(rèn) 沒有類型的 參數(shù) 和 返回值 為 int 類型;
- 2.舉例 :
等價(jià)于
int fun(int i) {return i; }- 3.代碼示例 :
4.可變參數(shù) 的 定義 和 使用
(1) 簡介
可變參數(shù)簡介 :
- 1.描述 : 函數(shù)可以接收的參數(shù)個(gè)數(shù)是不定的, 根據(jù)調(diào)用的需求決定有幾個(gè)參數(shù);
- 2.依賴頭文件 : 如果要使用可變參數(shù), 需要導(dǎo)入 stdarg.h 頭文件;
- 3.核心用法 : va_list, va_start, va_end, va_arg 配合使用, 訪問可變參數(shù)值;
可變參數(shù)示例 :
- 1.函數(shù)名相同, 參數(shù)個(gè)數(shù)不同 : open 函數(shù), 有兩種用法, 一個(gè)有 2 個(gè)參數(shù) int open(const char *pathname, int flags) , 一個(gè)有三個(gè)參數(shù) int open(const char *pathname, int flags, mode_t mode) , C 語言中明顯沒有重載, 這里是用可變參數(shù)來實(shí)現(xiàn)的 ; 使用 man 2 open 命令查看 open 函數(shù)的文檔;
可變參數(shù)的注意點(diǎn) :
- 1.取值必須順序進(jìn)行 : 讀取可變參數(shù)的值時(shí), 必須從頭到尾按照前后順序讀取, 不能跳過任何一個(gè)參數(shù);
- 2.必須確定1個(gè)參數(shù) : 參數(shù)列表中必須有一個(gè)命名確定的參數(shù);
- 3.可變參數(shù)數(shù)量無法確定 : 使用 va_arg 獲取 va_list 中的值時(shí), 無法判斷實(shí)際有多少個(gè)參數(shù);
- 4.可變參數(shù)類型無法確定 : 使用 va_arg 獲取 va_list 中的值時(shí), 無法判斷某個(gè)參數(shù)是什么類型的;
依次讀取可變參數(shù)時(shí), 注意 可變參數(shù) 的 數(shù)量 和 類型, 每個(gè)位置的參數(shù) 是 什么類型, 一定不要讀取錯(cuò)誤, 否則會產(chǎn)生不可預(yù)測的后果;
(2) 代碼示例 ( 定義 使用 可變參數(shù) )
代碼示例 :
- 1.代碼 :
- 2.編譯運(yùn)行結(jié)果 :
三. 函數(shù) 與 宏
1. 函數(shù) 與 宏 對比案例
(1) 函數(shù) 和 宏 的案例
代碼示例 : 分別使用 函數(shù) 和 宏 將數(shù)組數(shù)據(jù)清零;
- 1.代碼 :
- 2.編譯運(yùn)行結(jié)果 :
雖然看起來 函數(shù) 和 宏實(shí)現(xiàn)了相同的功能, 但是它們有很大的區(qū)別;
2. 函數(shù) 和 宏 的分析
(1) 函數(shù) 和 宏 分析
函數(shù) 和 宏 分析 :
- 1.宏處理 : 宏定義是在預(yù)處理階段直接進(jìn)行宏替換, 代碼直接復(fù)制到宏調(diào)用的位置, 由于宏在預(yù)處理階段就被處理了, 編譯器是不知道宏的存在的;
- 2.函數(shù)處理 : 函數(shù)是需要編譯器進(jìn)行編譯的, 編譯器有決定函數(shù)調(diào)用行為的義務(wù);
- 3.宏的弊端 ( 代碼量 ) : 每調(diào)用一次宏, 在預(yù)處理階段都要進(jìn)行一次宏替換, 會造成代碼量的增加;
- 4.函數(shù)優(yōu)勢 ( 代碼量 ) : 函數(shù)執(zhí)行是通過跳轉(zhuǎn)來實(shí)現(xiàn)的, 代碼量不會增加;
- 5.宏的優(yōu)勢 ( 效率 ) : 宏 的執(zhí)行效率 高于 函數(shù), 宏定義是在預(yù)編譯階段直接進(jìn)行代碼替換, 沒有調(diào)用開銷;
- 6.函數(shù)的弊端 ( 效率 ) : 函數(shù)執(zhí)行的時(shí)候需要跳轉(zhuǎn), 以及創(chuàng)建對應(yīng)的活動記錄( 棧 ), 效率要低于宏;
3. 函數(shù) 與 宏 的 利弊
(1) 宏 優(yōu)勢 和 弊端
宏的優(yōu)勢和弊端 : 宏的執(zhí)行效率要高于函數(shù), 但是使用宏會有很大的副作用, 非常容易出錯(cuò), 下面的例子說明這種弊端;
代碼示例 :
- 1.代碼 :
- 2.編譯運(yùn)行結(jié)果 :
- 3.查看預(yù)編譯文件 : 使用 gcc -E test_1.c -o test_1.i 指令, 將預(yù)編譯文件輸出到 test_1.i 目錄中; 下面是預(yù)編譯文件的一部分 ;
(2) 函數(shù) 的 優(yōu)勢 和 弊端
函數(shù)的優(yōu)缺點(diǎn) :
- 1.函數(shù)優(yōu)勢 : 函數(shù)調(diào)用需要將實(shí)參傳遞給形參, 沒有宏替換這樣的副作用;
- 2.弊端 ( 效率低 ) : 函數(shù)執(zhí)行需要跳轉(zhuǎn), 同時(shí)也需要建立活動對象對象 ( 如 函數(shù)棧 ) 來存儲相關(guān)的信息, 需要犧牲一些性能;
(3) 宏的無可替代性
宏 定義 優(yōu)勢 :
- 1.宏參數(shù)不限定類型 : 宏參數(shù) 可以是 任何 C 語言 的實(shí)體類型, 如 int, float, char, double 等;
- 2.宏參數(shù)可以使類型名稱 : 類型的名稱也可以作為宏的參數(shù);
4. 總結(jié)
(1) 宏 定義 和 函數(shù) 總結(jié)
宏定義 和 函數(shù) 小結(jié) :
- 1.宏定義 : 宏 的 參數(shù) 可以 是 C 語言中 的 任何類型的 ( 優(yōu)勢 ) , 宏的執(zhí)行效率 高 ( 優(yōu)勢 ), 但是容易出錯(cuò) ( 弊端 );
- 2.函數(shù) : 函數(shù) 參數(shù) 的 類型是固定的, 其 執(zhí)行效率低于宏, 但是不容易出錯(cuò);
- 3.宏定義 和 函數(shù)之間的關(guān)系 : 這兩者不是競爭對手, 宏定義可以實(shí)現(xiàn)一些函數(shù)無法實(shí)現(xiàn)的功能;
四. 函數(shù)的調(diào)用約定
1. 函數(shù)的活動記錄 分析
(1) 函數(shù)的活動記錄
活動記錄概述 : 函數(shù)調(diào)用時(shí) 將 下面一系列的信息 記錄在 活動記錄中 ;
1.臨時(shí)變量域 : 存放一些運(yùn)算的臨時(shí)變量的值, 如自增運(yùn)算, 在到順序點(diǎn)之前的數(shù)值是存在臨時(shí)變量域中的;
后置操作 自增 原理 : i++ 自增運(yùn)算 進(jìn)行的操作 :
( 1 ) 生成臨時(shí)變量 : 在內(nèi)存中生成臨時(shí)變量 tmp ;
( 2 ) 臨時(shí)變量賦值 : 將 i 的值賦值給臨時(shí)變量, tmp = i ;
( 3 ) 進(jìn)行加 1 操作 : 將 i + 1 并賦值給 i;
示例 : 定義函數(shù) fun(int a, int b), 傳入 fun(i, i++), 傳入后 獲取的實(shí)參值分別是 2 和 1;
在函數(shù)傳入?yún)?shù)達(dá)到順序點(diǎn)之后開始取值, 函數(shù)到達(dá)順序點(diǎn)之后, 上面的三個(gè)步驟就執(zhí)行完畢, 形參 a 從內(nèi)存中取值, i 的值是2, 形參 b 從臨時(shí)變量域中取值, 即 tmp 的值, 取值是 1;2.局部變量域 : 用于存放 函數(shù) 中定義 的局部變量, 該變量的生命周期是局部變量執(zhí)行完畢;
- 3.機(jī)器狀態(tài)域 : 保存 函數(shù)調(diào)用 之前 機(jī)器狀態(tài) 相關(guān)信息, 包括 寄存器值 和 返回地址, 如 esp 指針, ebp 指針;
- 4.實(shí)參數(shù)域 : 保存 函數(shù)的實(shí)參信息 ;
- 5.返回值域 : 存放 函數(shù)的返回值 ;
2. 函數(shù)的調(diào)用約定概述
(1) 參數(shù)入棧 問題描述
參數(shù)入棧問題 : 函數(shù)參數(shù)的計(jì)算次序是不固定的, 嚴(yán)重依賴于編譯器的實(shí)現(xiàn), 編譯器中函數(shù)參數(shù)入棧次序;
- 1.參數(shù)傳遞順序 : 函數(shù)的參數(shù) 實(shí)參傳遞給形參 是從左到右傳遞 還是 從右到左傳遞;
- 2.堆棧清理 : 是函數(shù)的調(diào)用者清理 還是 由 函數(shù)本身清理 ;
參數(shù)入棧 棧維護(hù) 問題示例 :
- 1.多參數(shù)函數(shù)定義 : 定義一個(gè)函數(shù) fun(int a, int b, int c) , 其中有 3 個(gè)參數(shù);
- 2.函數(shù)調(diào)用 : 當(dāng)發(fā)生函數(shù)調(diào)用時(shí) fun(1, 2, 3), 傳入三個(gè) int 類型的參數(shù), 這三個(gè)參數(shù)肯定有一個(gè)傳遞順序, 這個(gè)傳遞順序可以約定;
- ( 1 ) 從左向右入棧 : 將 1, 2, 3 依次 傳入 函數(shù)中 ;
- ( 2 ) 從右向左入棧 : 將 3, 2, 1 依次 傳入 函數(shù)中 ;
- 3.棧維護(hù) : 在 fun1() 函數(shù)中 調(diào)用 fun2() 函數(shù), 會創(chuàng)建 fun2() 函數(shù)的 活動記錄 (棧), 當(dāng) fun2() 函數(shù)執(zhí)行完畢 返回的時(shí)候, 該 fun2 函數(shù)的棧空間是由誰 ( fun1 或 fun2 函數(shù) ) 負(fù)責(zé)釋放的;
函數(shù)參數(shù)計(jì)算次序依賴于編輯器實(shí)現(xiàn), 函數(shù)參數(shù)入棧的順序可以自己設(shè)置;
(2) 參數(shù)傳遞順序的調(diào)用約定
函數(shù)參數(shù)調(diào)用約定 :
- 1.函數(shù)調(diào)用行為 : 函數(shù)調(diào)用時(shí) 參數(shù) 傳遞給 被調(diào)用的 函數(shù), 返回值被返回給 調(diào)用函數(shù) ;
- 2.調(diào)用約定作用 : 調(diào)用約定 是 用來規(guī)定 ① 參數(shù) 是通過什么方式 傳遞到 棧空間 ( 活動記錄 ) 中, ② 棧 由誰來 清理 ;
- 3.參數(shù)傳遞順序 ( 右到左 ) : 從右到左入棧使用 __stdcall, __cdecl, __thiscall 關(guān)鍵字, 放在 函數(shù)返回值之前;
- 4.參數(shù)傳遞順序 ( 左到右 ) : 從左到右入棧使用 __pascal, __fastcall 關(guān)鍵字, 放在 函數(shù)返回值之前;
- 5.調(diào)用堆棧的清理工作 : ① 調(diào)用者負(fù)責(zé)清理調(diào)用堆棧; ② 被調(diào)用的函數(shù)返回之前清理堆棧;
五. 函數(shù)設(shè)計(jì)技巧
函數(shù)設(shè)計(jì)技巧 :
- 1.避免使用全局變量 : 在函數(shù)中盡量避免使用全局變量, 讓函數(shù)形成一個(gè)獨(dú)立功能模塊;
- 2.參數(shù)傳遞全局變量 : 如果必須使用到全局變量, 那么多設(shè)計(jì)一個(gè)參數(shù), 用于傳入全局變量;
- 3.參數(shù)名稱可讀性 : 盡量不要使用無意義的字符串作為參數(shù)變量名;
- 4.參數(shù)常量 : 如果參數(shù)是一個(gè)指針, 該指針僅用于輸入作用, 盡量使用 const 修飾該指針參數(shù), 防止該指針在函數(shù)體內(nèi)被修改;
- 5.返回類型不能省略 : 函數(shù)的返回類型不能省略, 如果省略了返回值, 那么返回值默認(rèn) int;
- 6.參數(shù)檢測 : 在函數(shù)開始位置, 需要檢測函數(shù)參數(shù)的合法性, 避免不必要的錯(cuò)誤, 尤其是指針類型的參數(shù);
- 7.棧內(nèi)存指針 : 返回值 絕對不能是 局部變量指針, 即 指針指向的位置是 棧內(nèi)存位置, 棧內(nèi)存在返回時(shí)會銷毀, 不能再函數(shù)運(yùn)行結(jié)束后使用 ;
- 8.代碼量 : 函數(shù)的代碼量盡量控制在一定數(shù)目, 50 ~ 80 行, 符合模塊化設(shè)計(jì)規(guī)則;
- 9.輸入輸出固定 : 函數(shù)在輸入相同的參數(shù), 其輸出也要相同, 盡量不要在函數(shù)體內(nèi)使用 static 局部變量, 這樣函數(shù)帶記憶功能, 增加函數(shù)的復(fù)雜度;
- 10.參數(shù)控制 : 編寫函數(shù)的時(shí)候, 函數(shù)的參數(shù)盡量控制在 4 個(gè)以內(nèi), 方便使用;
- 11.函數(shù)返回值設(shè)計(jì) : 有時(shí)候函數(shù)不需要返回值, 或者返回值使用指針參數(shù)設(shè)置, 但是為了增加靈活性, 可以附加返回值; 如 支持 鏈?zhǔn)奖磉_(dá)式 功能;
總結(jié)
以上是生活随笔為你收集整理的【C 语言】C 语言 函数 详解 ( 函数本质 | 顺序点 | 可变参数 | 函数调用 | 函数活动记录 | 函数设计 ) [ C语言核心概念 ]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【C 语言】内存管理 ( 动态内存分配
- 下一篇: 【 Markdown 】Markdown