C語言 函數與遞歸(其二)
?
書接上回
?
? 上期主要是C語言中關于函數的部分知識,我向大家介紹了函數的定義,庫函數,自定義函數的定義和使用方法及函數參數的類型。這些內容都是對函數的基本認識,而函數在編程過程中的具體使用和更深層次的知識我們將在本期及下期內容介紹。話不多說,我們開始本期的學習
?本期將在上期基礎之上繼續(xù)加深對函數的認識
?1.函數的兩種調用方法和區(qū)別
?2.函數的嵌套調用和鏈式訪問
?3.函數的聲明和定義
函數的調用:
? 傳值調用
?? ??函數的形參和實參分別占有不同的內存塊,對形參的修改不會影響實參
? 傳址調用
? ? ? 傳址調用是把函數外部創(chuàng)建變量的內存地址傳遞給函數參數的一種調用函數的方式
? ? ? ?此傳參方式可以讓函數和函數外面的變量建立起真正的聯系。也就是說,函數內部可以直接操作函數外部的變量。
? ? ?只聽定義會一頭霧水,接下來我為大家提供一個具體問題來方便大家感受兩種調用的區(qū)別。
? ? ?應用:【給出兩個變量a,b。?要求交換二者的值
#include <stdio.h>
void?swap1(int?x,int?y)//此函數無返回值,因此用"void"作為返回值類型
{
?int tmp=0;
?tmp=x;
?x=y;
?y=tmp;
}//定義函數,交換變量值
int?main()
{
??int?a=10;
??int?b=20;
??swap1(a,b);//無返回值函數的執(zhí)行方法,我們接下來會提到
??printf("a=?%d?b=?%d",a,b);
??return 0;
}
? ?如上述函數,我們看似成功地完成了任務,但當我們在執(zhí)行程序之后,屏幕上打印出來的卻仍是"a=10?b=20",這說明我們剛才所寫函數并不能完成我們所預期的功能,那問題出在哪里呢?請看接下來的代碼:
#include<stdio.h>
void?swap2(int*?x,int*?y)//此處與上面函數不同,體會"int"與"int*"的區(qū)別
{
??int tmp=0;
??tmp=*x;
??*x=*y;
??*y=tmp;
}
int main()
{
?int a=10;
?int b=20;
??swap2(&a,&b);//此處也是不同之處
??printf("a= %d b=%d", a, b);
??return 0;
}
? ??而這個代碼運行的結果就達到了我們想要的效果,這就是兩種調用的不同之處,傳值調用是將實際參數拷貝到函數的形式參數中,在經過一系列運算后得出結果,它注重的是返回值;而傳址調用則是直接將存放實際參數的地址傳遞給函數,一般用于需要對函數參數自身改變的程序,如上面提到的交換兩個變量的值,這種調用一般來說都是沒有返回值的。
? ? 當我們在定義完一個函數,要在主函數中去使用時,我們仍需要注意一個細節(jié),那就是在使用有返回值的函數時需要有一個變量去接收,而沒有返回值的函數就不需要考慮這個問題了。
??在聽完對兩種調用的介紹后,相信大家對函數調用已經有初步的認識了,那么我們接下來看幾道關于函數調用的問題:
? ? ? ?1.寫一個函數判斷一個數是否是素數
? ? ? ?2.寫一個函數判斷一年是否是閏年
? ? ? ?3.寫一個函數實現一個整型有序數組的二分查找
?? ? ??4.寫一個函數,每調用一次,就會將變量"num"的值加一
? ?由于篇幅有限,我這里就不給出以上問題的詳解了,具體的習題集合我會之后專門出一個合集來介紹。以上問題需要用到的函數調用方法分別是1~3:傳值調用,4:傳址調用。
? ?而我們在實際的使用過程中還是遵循“需要對函數參數自身改變的就用傳址調用;需要在運算后得出一個新結果的就用傳值調用”這一原則。
? ?一句話,熟能生巧,用多了我們自然而然就會了
函數的嵌套調用和鏈式訪問
? ?函數與函數之間是可以有機結合的
嵌套調用
??在函數中可以調用另一個函數,這種方式叫嵌套調用。由于比較簡單,這里就不舉例子了
鏈式訪問
??把一個函數的返回值作為另一個函數的參數。這個概念同樣比較好理解,不過這里有個很有趣的例子
#include<stdio.h>
int?main()
{
??printf("%d",printf("%d",printf("%d",43)));
??//結果是啥???
??return 0;
}
大家的第一反應應該都是認為屏幕上會打印出“43 43 43”,但是在程序運行后,屏幕上卻打印出了“4321”。問題出在哪兒呢?原來c語言規(guī)定,printf的返回值就是它所打印的字符個數,在上述例子中,最內層的printf打印了“43”,所以它的返回值(就是2)成為了第二個printf的參數,以此類推,屏幕上就打印出了上述的結果。
函數的聲明和定義
函數聲明:
? ? ? ? ?1.告訴編譯器有一個函數叫什么,參數是什么,返回類型是什么。但是具體是不是存在無關緊要。
? ? ? ? ? 2.函數的聲明一般出現在函數的使用之前。要滿足先聲明后使用。
? ? ? ? ??3.函數的聲明一般要放在頭文件中。
函數定義:
? ? ? ??函數定義是指函數的具體實現,交代函數的功能實現。
? ? ??下面舉一個簡單的函數聲明的例子:
int add(int ,int );
int?main()
{
?int a=10;
??int?b=20;
??int?sum?=0;
??sum=add(a,b);
??printf("%d",sum);
??return 0;
}
int?add(int?x,int?y)
{
??return (x+y);
}
? 如上述代碼所寫,我們先在程序最上面聲明了存在“add”這一函數,所以程序在執(zhí)行時就不會報錯。我們要知道的是,C語言在執(zhí)行時是從上到下依次執(zhí)行的。如果不事先聲明的話,在函數位于主函數后面的情況下去運行,程序就會報錯。
? 當然我們聲明函數并不是用來寫上面的代碼,這種寫法非常睿智,我只是舉個函數聲明的例子。函數聲明更多情況下適用于一些比較復雜的程序,當我們需要寫一些復雜的代碼時,由于多人分工,大家會分別負責不同的模塊,這時我們就可以創(chuàng)建多個源文件和對應的頭文件分別進行編程,在使用時就會方便很多了
