C語言的函數(shù)概念與規(guī)則你了解嗎
一、函數(shù)概念
函數(shù)三要素
函數(shù)名 (地址)輸入?yún)?shù)輸出參數(shù)
int fun(int,int,char){xxx}
1.傳入?yún)?shù)
實參: 調(diào)用時傳入的具體值
形參: 函數(shù)內(nèi)部接受的變量
2.返回值
返回函數(shù)處理的結(jié)果數(shù)據(jù)(另一種方式是函數(shù)外部使用址傳遞參數(shù),來獲得函數(shù)處理的數(shù)據(jù))
二、函數(shù)參數(shù)
C語言函數(shù)傳參,實際上就是copy的過程,參數(shù)類型的區(qū)別在于copy的多少的問題,當(dāng)然類型不同可能存在丟失部分數(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)先級,而不是默認從右往左讀
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.通過二級指針,將一組函數(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)存地址上,所以會數(shù)據(jù)被修改
僅查看時用值傳遞
讀寫資源或節(jié)省資源時 使用址傳遞
五、函數(shù)連續(xù)空間的傳遞
連續(xù)空間傳遞,一般都會選擇使用址傳遞,使用值傳遞浪費資源過多
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, "手機", 20); product.price = 3666; println(product); //main:手機 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]等價于*product此處可以替換,但是需要加()讓程序優(yōu)先識別,即:(*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, "手機", 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];在定義時,編譯器已經(jīng)知道其首地址被names標(biāo)簽描述,因此數(shù)組作為形參時只需要傳遞數(shù)組的標(biāo)簽名和偏移量即可names[10]即可
數(shù)組址傳遞數(shù)據(jù)示例
//C語言現(xiàn)在優(yōu)化允許使用int p[10],便于閱讀 實際上效果與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],便于閱讀 實際上效果與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ù)時使用const修飾指針?biāo)傅膬?nèi)存地址即可,如const char *p,這也是開發(fā)時默認的規(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)建的變量地址,會被回收:異常)
int * func();
char * func1() { return "HelloWorld"; } int main() { char *p= func1(); //HelloWorld printf("%s",p); return 0; }
工程中一般不使用上述方案(常量區(qū)存儲),意義不大,通常使用靜態(tài)區(qū)存儲局部變量(程序結(jié)束才回收),即如下方法
char * func1() { static char abc[] = "HelloWorld"; return abc; } int main() { char *p= func1(); //HelloWorld printf("%s",p); return 0; }
也可以使用堆區(qū)存儲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)容!