C語言的函數(shù)概念與規(guī)則你了解嗎
一、函數(shù)概念
函數(shù)三要素
函數(shù)名 (地址)輸入?yún)?shù)輸出參數(shù)
int fun(int,int,char){xxx}
1.傳入?yún)?shù)
實(shí)參: 調(diào)用時(shí)傳入的具體值
形參: 函數(shù)內(nèi)部接受的變量
2.返回值
返回函數(shù)處理的結(jié)果數(shù)據(jù)(另一種方式是函數(shù)外部使用址傳遞參數(shù),來獲得函數(shù)處理的數(shù)據(jù))
二、函數(shù)參數(shù)
C語言函數(shù)傳參,實(shí)際上就是copy的過程,參數(shù)類型的區(qū)別在于copy的多少的問題,當(dāng)然類型不同可能存在丟失部分?jǐn)?shù)據(jù)情況(copy不完整)
void printAddress(int a) { //printAddress a地址:0xc printf("printAddress a地址:%p\n",a); } int main() { int a = 12; //main a地址:0xc printf("main a地址:%p\n",a); printAddress(a); return 0; }
void printAddress(int a) { //printAddress a地址:0xffffff9b printf("printAddress a地址:%p\n",a); } int main() { char a = "ABCDE"; //main a地址:0xffffff9b printf("main a地址:%p\n",a); printAddress(a); return 0; }
void printAddress(int a) { //printAddress a地址:0xeccc1e18 printf("printAddress a地址:%p\n", a); } int main() { int a = 12; int *p_a; p_a = &a; //main a地址:0x7ffeeccc1e18 printf("main a地址:%p\n", p_a); printAddress(p_a); return 0; }
三、指針函數(shù)-函數(shù)名指針化
通過函數(shù)三要素可以得出,指針也可以表示函數(shù)
int (*p)(int,int,char){xxx} 與指針指向二維數(shù)組類似,指針必須要加(),來提高程序?qū)λ庾x的優(yōu)先級(jí),而不是默認(rèn)從右往左讀
1.指針指向其他函數(shù)的函數(shù)名(標(biāo)簽)效果
int main() { int (*printf2)(const char *,...); //HelloWOrld printf("HelloWOrld\n"); printf2 = printf; //FFFF printf2("FFFF\n"); return 0; }
2.指針指向其他函數(shù)的地址效果
int main() { int (*printf2)(const char *, ...); //HelloWOrld 0x7fff204b50b8 printf("HelloWOrld %p \n", printf); printf2 = (int (*)(const char *, ...))0x7fff204b50b8; //FFFF printf2("FFFF\n"); return 0; }
3.通過二級(jí)指針,將一組函數(shù)線性化
int (*p[5])(int,int); p[0]=func1; p[1]=func2; p[2]=func3; //使用效果,可以替代switch p[day](8,9);
四、函數(shù)值傳遞和址傳遞
值傳遞:void fun1(int a){...}傳入數(shù)據(jù)a copy到函數(shù)中,函數(shù)中數(shù)據(jù)的修改不影響函數(shù)外被傳入的數(shù)據(jù)
址傳遞:void func2(*a){...}傳入數(shù)據(jù)地址&a copy到函數(shù)中,函數(shù)中數(shù)據(jù)的修改是在該地址上修改的,函數(shù)外被傳入的數(shù)據(jù)也處在該內(nèi)存地址上,所以會(huì)數(shù)據(jù)被修改
僅查看時(shí)用值傳遞
讀寫資源或節(jié)省資源時(shí) 使用址傳遞
五、函數(shù)連續(xù)空間的傳遞
連續(xù)空間傳遞,一般都會(huì)選擇使用址傳遞,使用值傳遞浪費(fèi)資源過多
1.結(jié)構(gòu)體(變量)
值傳遞示例
struct product_t { char name[20]; int price; }; void println(struct product_t product) { strncpy(product.name, "牙刷", 20); product.price = 3; //println:牙刷 printf("println:%s \n", product.name); //println:3 printf("println:%d \n", product.price); } int main() { struct product_t product; strncpy(product.name, "手機(jī)", 20); product.price = 3666; println(product); //main:手機(jī) printf("main:%s \n", product.name); //main:3666 printf("main:%d \n", product.price); return 0; }
址傳遞示例 (通過指針)
struct product_t { char name[20]; int price; }; void println(struct product_t *product) { //product[0]等價(jià)于*product此處可以替換,但是需要加()讓程序優(yōu)先識(shí)別,即:(*product) strncpy(product[0].name, "牙刷", 20); product[0].price = 3; //println:牙刷 printf("println:%s \n", product[0].name); //println:3 printf("println:%d \n", product[0].price); } int main() { struct product_t product; strncpy(product.name, "手機(jī)", 20); product.price = 3666; println(&product); //main:牙刷 printf("main:%s \n", product.name); //main:3 printf("main:%d \n", product.price); return 0; }
2.數(shù)組(標(biāo)簽)
數(shù)組int names[10];在定義時(shí),編譯器已經(jīng)知道其首地址被names標(biāo)簽描述,因此數(shù)組作為形參時(shí)只需要傳遞數(shù)組的標(biāo)簽名和偏移量即可names[10]即可
數(shù)組址傳遞數(shù)據(jù)示例
//C語言現(xiàn)在優(yōu)化允許使用int p[10],便于閱讀 實(shí)際上效果與int *p一致,都是址傳遞 void println(int *p) { p[0] = 77; //println:77 printf("println:%d \n", p[0]); //println:11 printf("println:%d \n", p[1]); } int main() { int prices[10] = {22, 11, 55}; println(prices); //main:77 printf("main:%d \n", prices[0]); //main:11 printf("main:%d \n", prices[1]); return 0; }
數(shù)組址傳遞地址示例
//C語言現(xiàn)在優(yōu)化允許使用int p[10],便于閱讀 實(shí)際上效果與int *p一致,都是址傳遞 void println(int *p) { p[0] = 77; //println:0x7ffee8964df0 printf("println:%p \n", &p[0]); //println:0x7ffee8964df4 printf("println:%p \n", &p[1]); } int main() { int prices[10] = {22, 11, 55}; println(prices); //main:0x7ffee8964df0 printf("main:%p \n", &prices[0]); //main:0x7ffee8964df4 printf("main:%p \n", &prices[1]); return 0; }
如上兩段代碼,數(shù)組傳遞為址傳遞,數(shù)組標(biāo)簽名本身就是地址的標(biāo)簽,與指針非常相似
3.連續(xù)空間的只讀
定義參數(shù)時(shí)使用const修飾指針?biāo)傅膬?nèi)存地址即可,如const char *p,這也是開發(fā)時(shí)默認(rèn)的規(guī)范
讀寫函數(shù)形參:char *p;
只讀函數(shù)形參:const char *p
如strncpy函數(shù)的源碼:char *stpncpy(char *dst, const char *src, size_t n)
六、函數(shù)返回值
返回值與參數(shù)一樣,也是copy的原理傳遞,可以copy值,也可以copy地址
char func1() { char s = 'A'; return s; } int main() { char s= func1(); //41 printf("%X",s); return 0; }
注意:指針是C語言中返回空間的唯一類型 (無法返回函數(shù)內(nèi)部創(chuàng)建的變量地址,會(huì)被回收:異常)
int * func();
char * func1() { return "HelloWorld"; } int main() { char *p= func1(); //HelloWorld printf("%s",p); return 0; }
工程中一般不使用上述方案(常量區(qū)存儲(chǔ)),意義不大,通常使用靜態(tài)區(qū)存儲(chǔ)局部變量(程序結(jié)束才回收),即如下方法
char * func1() { static char abc[] = "HelloWorld"; return abc; } int main() { char *p= func1(); //HelloWorld printf("%s",p); return 0; }
也可以使用堆區(qū)存儲(chǔ)malloc()函數(shù)中創(chuàng)建的變量,注意使用完畢后一定要釋放內(nèi)存(free())
char * func1() { char *s = (char *)malloc(50); strncpy(s,"HelloWorld",50); return s; } int main() { char *p= func1(); //HelloWorld printf("%s",p); free(p); return 0; }
總結(jié)
本章主要為C語言函數(shù)概念和規(guī)則
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Qt編寫地圖實(shí)現(xiàn)實(shí)時(shí)動(dòng)態(tài)軌跡效果
實(shí)時(shí)動(dòng)態(tài)軌跡主要是需要在地圖上動(dòng)態(tài)顯示GPS的運(yùn)動(dòng)軌跡,也是編寫地圖時(shí)一個(gè)重要的功能。本文將利用Qt實(shí)現(xiàn)這一功能,需要的可以參考一下2022-02-02C++實(shí)現(xiàn)簡(jiǎn)單的ls命令及其原理
這篇文章主要介紹了C++實(shí)現(xiàn)簡(jiǎn)單的ls命令及其原理,C++實(shí)現(xiàn)ls命令可通過調(diào)用系統(tǒng)函數(shù)實(shí)現(xiàn)讀取目錄中的文件名和屬性,再通過標(biāo)準(zhǔn)輸出進(jìn)行顯示,需要的朋友可以參考下2023-05-05使用root權(quán)限運(yùn)行自己所編譯程序的解決方法
本篇文章介紹了,使用root權(quán)限運(yùn)行自己所編譯程序的解決方法。需要的朋友參考下2013-05-05C++中對(duì)C語言結(jié)構(gòu)體用法的擴(kuò)充
今天小編就為大家分享一篇關(guān)于C++中對(duì)C語言結(jié)構(gòu)體用法的擴(kuò)充,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12基于C++實(shí)現(xiàn)的哈夫曼編碼解碼操作示例
這篇文章主要介紹了基于C++實(shí)現(xiàn)的哈夫曼編碼解碼操作,結(jié)合實(shí)例形式分析了C++實(shí)現(xiàn)的哈夫曼編碼解碼相關(guān)定義與使用技巧,需要的朋友可以參考下2018-04-04