C語(yǔ)言函數(shù)一本道來(lái)

姓名:王懷帥? 學(xué)號(hào):16040410035

轉(zhuǎn)載自:http://www.itdecent.cn/p/89c81a34a83a=有修改

【嵌牛導(dǎo)讀】:C語(yǔ)言中函數(shù)對(duì)各類問(wèn)題的實(shí)際性解決方案

【嵌牛鼻子】:C語(yǔ)言函數(shù)

【嵌牛提問(wèn)】:如何理解函數(shù)在C語(yǔ)言中的作用以及如何使用這些函數(shù)?

【嵌牛正文】:

函數(shù)的由來(lái)

程序=數(shù)據(jù)+算法

C程序=數(shù)據(jù)+函數(shù)

模塊化程序設(shè)計(jì)

模塊化程序設(shè)計(jì).png

面向過(guò)程的程序設(shè)計(jì)

以過(guò)程為中心的編程思想

首先將復(fù)雜的問(wèn)題,分解為一個(gè)個(gè)容易的問(wèn)題

分解過(guò)后的問(wèn)題可以按照步驟一步步完成

函數(shù)是C語(yǔ)言面向過(guò)程的一種體現(xiàn)

解決問(wèn)題的每個(gè)步驟可以用函數(shù)來(lái)實(shí)現(xiàn)

聲明&&定義

聲明就是預(yù)先告訴編譯器實(shí)體的存在

定義就是明確指示編譯器實(shí)體的意義

#include

extern int g_var;//全局的

void f(int i, int j);//函數(shù)聲明

int main()

{

//extern int g_var;//局部變量聲明

int g(int x);//函數(shù)聲明

g_var = 10;

f(1, 2);

printf("%d\n", g(3));

return 0;

}

void f(int i, int j)//函數(shù)定義

{

printf("i + j = %d\n", i + j);

}

int g(int x)//函數(shù)定義

{

return 2 * x + g_var;

}

文件二

int g_var = 0;

函數(shù)的參數(shù)

函數(shù)的參數(shù)在本質(zhì)上與局部變量相同,都是在棧上面分配空間

函數(shù)參數(shù)的初始值是函數(shù)調(diào)用時(shí)的實(shí)參值

#include

int f(int i, int j)

{

printf("%d, %d\n", i, j);

}

int main()

{

int k = 1;

f(k, k++);

printf("%d\n", k);

return 0;

}

這里的輸出是2,1,2

解釋

函數(shù)的參數(shù)的求值順序是依賴于編譯器的實(shí)現(xiàn)!

在程序到達(dá)順序點(diǎn)的時(shí)候,之前所做的一切操作必須反映到后續(xù)訪問(wèn)中.

也就是說(shuō)在這個(gè)例子中,在gcc編譯器下面,先傳第二個(gè)參數(shù)到函數(shù),然后,再進(jìn)行++運(yùn)算,在進(jìn)行第一個(gè)參數(shù)傳遞

.

可變參數(shù)列表

可變參數(shù)的含義

C語(yǔ)言中可以定義參數(shù)可變的函數(shù)

參數(shù)可變的函數(shù)實(shí)現(xiàn)依賴于stdarg.h頭文件

va_list變量va_start(),va_end和va_arg配合使用能夠訪問(wèn)參數(shù)值

在C語(yǔ)言中是沒(méi)有重載,但是可以使用可變參數(shù)列表

#include

#include

float average(int n, ...)

{

va_list args;

int i = 0;

float sum = 0;

va_start(args, n);

for(i=0; i

{

sum += va_arg(args, int);

}

va_end(args);

return sum / n;

}

int main()

{

printf("%f\n", average(5, 1, 2, 3, 4, 5));

printf("%f\n", average(4, 1, 2, 3, 4));

return 0;

}

可變參數(shù)的限制

可變參數(shù)必須從頭到尾按照順序逐個(gè)訪問(wèn)

參數(shù)列表至少一個(gè)確定命名的參數(shù)

可變參數(shù)宏是沒(méi)有辦法判斷實(shí)際存在的參數(shù)的數(shù)量

可變參數(shù)宏無(wú)法判斷參數(shù)的實(shí)際類型

小結(jié)

可變參數(shù)是C語(yǔ)言提供的一種函數(shù)設(shè)計(jì)的技巧

可變參數(shù)提供了一種更方便的函數(shù)調(diào)用方式

可變參數(shù)必須順序的訪問(wèn)

無(wú)法直接訪問(wèn)可變參數(shù)列表中間的參數(shù)值

函數(shù)調(diào)用行為

活動(dòng)記錄

活動(dòng)記錄是函數(shù)調(diào)用時(shí)用于記錄一系列相關(guān)信息的記錄

臨時(shí)變量域:用來(lái)存放臨時(shí)變量的值,如k++的中間結(jié)果

局部變量域:用來(lái)存放函數(shù)本次執(zhí)行中的局部變量

機(jī)器狀態(tài)域:用來(lái)保存調(diào)用函數(shù)之前有關(guān)機(jī)器狀態(tài)的信息,包括各種寄存器的當(dāng)前值和返回地址等。(棧頂指針等)

實(shí)參域:用來(lái)存放函數(shù)實(shí)參信息

返回值域:為調(diào)用者函數(shù)存放返回值

函數(shù)參數(shù)計(jì)算的次序是依賴編譯器實(shí)現(xiàn)的,參數(shù)的入棧次序如何確定?

調(diào)用約定(在調(diào)用動(dòng)態(tài)連接庫(kù)的時(shí)候可以用)

當(dāng)函數(shù)被調(diào)用時(shí),參數(shù)會(huì)傳遞給被調(diào)用的函數(shù),函數(shù)調(diào)用約定就是描述是如何傳遞到??臻g的,以及??臻g由誰(shuí)維護(hù)

參數(shù)的傳遞順序

從右到左依次入棧: __stdcall,__cdecl,__thiscall

從左到右依次入棧:__pascal,__fastall

調(diào)用堆棧清理

調(diào)用者清除棧

被調(diào)用函數(shù)返回后清除棧

小結(jié)

函數(shù)調(diào)用時(shí)C語(yǔ)言的核心機(jī)制

活動(dòng)記錄保存了函數(shù)調(diào)用以及返回所需要的一切信息

調(diào)用約定是調(diào)用者和開(kāi)發(fā)者之間的調(diào)用協(xié)議,常用于不同的開(kāi)發(fā)者編寫的庫(kù)函數(shù)調(diào)用

函數(shù)的設(shè)計(jì)技巧

不要再函數(shù)中使用全局變量,盡量讓函數(shù)從意義上是一個(gè)獨(dú)立功能模塊

參數(shù)名要能夠體現(xiàn)參數(shù)意義

如果說(shuō)傳遞的參數(shù)為指針,且僅僅作輸入?yún)?shù)用,則應(yīng)在類型前加const,以防止該指針在函數(shù)體內(nèi)被惡意修改

不要省略返回值的類型,如果函數(shù)沒(méi)有返回值,那么應(yīng)當(dāng)聲明為void

在函數(shù)體的“入口處”,對(duì)參數(shù)的有效性進(jìn)行檢查,對(duì)指針的檢查尤為重要

語(yǔ)句不可返回指向“棧內(nèi)存”的“指針”,因?yàn)樵搩?nèi)存會(huì)在函數(shù)結(jié)束后銷毀

函數(shù)體的規(guī)模要小

相同的輸入應(yīng)當(dāng)產(chǎn)生相同的輸出,盡量避免函數(shù)帶有“記憶”功能少用static

避免函數(shù)有太多的參數(shù),參數(shù)個(gè)數(shù)應(yīng)當(dāng)控制在4個(gè)以內(nèi)

有時(shí)候函數(shù)不需要返回值,但是增加靈活性,可以附加返回值

函數(shù)名與返回值在語(yǔ)義上不能沖突

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容