C語言的函數概念與規則你瞭解嗎
一、函數概念
函數三要素
int fun(int,int,char){xxx}函數名 (地址)輸入參數輸出參數
1.傳入參數
實參: 調用時傳入的具體值
形參: 函數內部接受的變量
2.返回值
返回函數處理的結果數據(另一種方式是函數外部使用址傳遞參數,來獲得函數處理的數據)
二、函數參數
C語言函數傳參,實際上就是copy的過程,參數類型的區別在於copy的多少的問題,當然類型不同可能存在丟失部分數據情況(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; }
三、指針函數-函數名指針化
通過函數三要素可以得出,指針也可以表示函數
int (*p)(int,int,char){xxx} 與指針指向二維數組類似,指針必須要加(),來提高程序對他解讀的優先級,而不是默認從右往左讀
1.指針指向其他函數的函數名(標簽)效果
int main() { int (*printf2)(const char *,...); //HelloWOrld printf("HelloWOrld\n"); printf2 = printf; //FFFF printf2("FFFF\n"); return 0; }
2.指針指向其他函數的地址效果
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.通過二級指針,將一組函數線性化
int (*p[5])(int,int); p[0]=func1; p[1]=func2; p[2]=func3; //使用效果,可以替代switch p[day](8,9);
四、函數值傳遞和址傳遞
值傳遞:void fun1(int a){…}傳入數據a copy到函數中,函數中數據的修改不影響函數外被傳入的數據
址傳遞:void func2(*a){…}傳入數據地址&a copy到函數中,函數中數據的修改是在該地址上修改的,函數外被傳入的數據也處在該內存地址上,所以會數據被修改
僅查看時用值傳遞
讀寫資源或節省資源時 使用址傳遞
五、函數連續空間的傳遞
連續空間傳遞,一般都會選擇使用址傳遞,使用值傳遞浪費資源過多
1.結構體(變量)
值傳遞示例
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此處可以替換,但是需要加()讓程序優先識別,即:(*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.數組(標簽)
數組int names[10];在定義時,編譯器已經知道其首地址被names標簽描述,因此數組作為形參時隻需要傳遞數組的標簽名和偏移量即可names[10]即可
數組址傳遞數據示例
//C語言現在優化允許使用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; }
數組址傳遞地址示例
//C語言現在優化允許使用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; }
如上兩段代碼,數組傳遞為址傳遞,數組標簽名本身就是地址的標簽,與指針非常相似
3.連續空間的隻讀
定義參數時使用const修飾指針所指的內存地址即可,如const char *p,這也是開發時默認的規范
讀寫函數形參:char *p;
隻讀函數形參:const char *p
如strncpy函數的源碼:char *stpncpy(char *dst, const char *src, size_t n)
六、函數返回值
返回值與參數一樣,也是copy的原理傳遞,可以copy值,也可以copy地址
char func1() { char s = 'A'; return s; } int main() { char s= func1(); //41 printf("%X",s); return 0; }
註意:指針是C語言中返回空間的唯一類型 (無法返回函數內部創建的變量地址,會被回收:異常)
int * func();
char * func1() { return "HelloWorld"; } int main() { char *p= func1(); //HelloWorld printf("%s",p); return 0; }
工程中一般不使用上述方案(常量區存儲),意義不大,通常使用靜態區存儲局部變量(程序結束才回收),即如下方法
char * func1() { static char abc[] = "HelloWorld"; return abc; } int main() { char *p= func1(); //HelloWorld printf("%s",p); return 0; }
也可以使用堆區存儲malloc()函數中創建的變量,註意使用完畢後一定要釋放內存(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; }
總結
本章主要為C語言函數概念和規則
本篇文章就到這裡瞭,希望能給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!