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-02
C++實(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-05
C++中對(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

