這篇筆記主要是介紹C語言中的函數,包括函數的功能和定義等。閱讀本文預計需要 6 分鐘。
Day05 郝斌C語言自學視頻之C語言的函數
爲什麼需要函數
函數是C語言的基本單位,類是Java,C#,C++的基本單位。函數
是繼學習 C 語言流程控制
之後的第二個重點。那麼前人爲什麼會創造函數?我們爲什麼需要函數呢?主要是以下兩個原因:
-
使用函數可以避免重複性操作。
-
使用函數有利於程序的模塊化。
例 函數的作用
/*
時間:2020年2月22日14:01:19
功能:
函數的作用演示
總結:
1. 函數可以實現功能複用,減少代碼量
*/
# include <stdio.h>
// max 是函數名字,i 和 j 是形式參數,簡稱形參 void 表示函數沒有返回值。
void max(int i, int j)
{
if (i > j)
printf("%d\n", i);
else
printf("%d\n", j);
}
int main(void)
{
int a, b, c, d, e, f;
a = 1, b = 2, c = 3, d = 9, e = -5, f = 100; // 不推薦這麼寫
max(a, b);
max(c, d);
max(e, f);
/*
if (a > b)
printf("%d\n", a);
else
printf("%d\n", b);
if (c > d)
printf("%d\n", c);
else
printf("%d\n", d);
if (e > f)
printf("%d\n", e);
else
printf("%d\n", f);
*/
return 0;
}
/*
在VSCode中的輸出結果是:
--------------------------
2
9
100
--------------------------
*/
什麼是函數
邏輯上:函數是能夠完成特定功能的獨立的代碼單元。
物理上:函數能夠接收數據,對接收的數據進行處理,將數據處理的結果返回,當然也可以不返回任何值。
總結:函數是一個工具,它是爲了解決大量類似問題而設計的。函數可以當做一個黑匣子。
函數的分類
函數按照不同的分類方法,可以分爲以下類型:
- | - |
---|---|
有參函數 | 無參函數 |
有返回值函數 | 無返回值函數 |
庫函數 | 用戶自定義函數 |
值傳遞函數 | 地址傳遞函數 |
普通函數 | 主函數(main函數) |
如何定義使用函數
定義函數
格式:
函數的返回值 函數的名字(函數的形參列表)
{
函數的執行體
}
函數定義的本質是詳細描述函數之所以能夠實現某個特定功能的具體方法。
return 表達式;
的含義:
- 終止被調函數,向主調函數返回表達式的值。
- 如果表達式爲空,則只終止函數,不向主調函數返回任何值。
break
是用來終止循環和switch
的,return
是用來終止函數的。
例 break VS return
/*
時間:2020年2月22日15:31:31
功能:
break VS return
總結:
break 終止循環和 switch,return 終止函數。
*/
# include <stdio.h>
void f(void)
{
int i;
for (i=0; i<5; ++i)
{
printf("大家辛苦了!\n");
// break; // 終止循環
return; // 終止函數
}
printf("同志們好!\n");
}
int main(void)
{
f();
return 0;
}
/*
break 時在VSCode中的輸出結果是:
--------------------------
大家辛苦了!
同志們好!
--------------------------
return 時在VSCode中的輸出結果是:
--------------------------
大家辛苦了!
--------------------------
*/
注意:函數返回值的類型也稱爲函數的類型。因爲如果函數名前的返回值類型和函數執行體中的 return 表達式
中表達式的類型不同的話,則最終函數返回值的類型以函數名前的返回值類型爲準。
例 函數返回值類型的決定因素
/*
時間:2020年2月22日15:26:21
功能:
測試 函數返回值類型由誰決定
總結:
如果函數名前的返回值類型和函數執行體中的 `return 表達式` 中
表達式的類型不同的話,則最終函數返回值的類型,
以函數名前的返回值類型爲準。
*/
# include <stdio.h>
int f(void)
{
return 10.5; // 因爲函數的返回值類型是 int
// 所以最終 f() 返回的是 10 而不是 10.5
}
int main(void)
{
int i = 99;
double x = 6.6;
i = f();
x = f();
// printf("%d\n", i);
printf("%lf\n", x);
return 0;
}
/*
在VSCode中的輸出結果是:
--------------------------
10.000000
--------------------------
*/
注意事項
- 一個程序必須有且僅有一個主函數,即
main
函數。 - 主函數可以調用普通函數,普通函數不能調用主函數。
- 普通函數可以相互調用。
- 主函數是程序的入口,也是程序的出口。
- 形參和實參個數必須相同,位置一一對應,數據類型必須兼容。
- 函數調用和函數定義的順序問題。如果函數調用寫在了函數定義的前面,則必須加函數前置聲明。
函數前置聲明的作用:
- 告訴編譯器即將可能出現的若干個字母代表的是一個函數.
- 告訴編譯器即將可能出現的若干個字母所代表的的函數的形參和返回值的具體情況。
- 函數聲明是一個語句,末尾必須加分號。
- 對庫函數的聲明是通過
# include <庫函數所在的文件的名字.h>
來實現的
如何在軟件開發中合理的設計函數來解決實際問題
- 一個函數的功能儘量獨立,單一。
- 多學習,多模仿牛人的代碼。
例 函數功能單一的優勢
/*
時間:2020年2月24日11:25:24
目的:
求 1 到某個數字之間的所有素數,並將其輸出
總結:
把函數功能進行拆分,一個功能一個函數,代碼量更少,可重用性更高
*/
# include <stdio.h>
# include <stdbool.h>
// 本函數的功能是:判斷m是否是素數,是返回true,不是返回false
bool IsPrime(int m)
{
int i;
for (i=2; i<m; i++)
{
if (0 == m%i)
break;
}
if (i == m)
return true;
else
return false;
}
// 本函數功能是把 1-n 之間所有的函數在顯示器上輸出
void TraverseVal(int n)
{
int i;
for (i=2; i<=n; ++i)
{
if (IsPrime(i))
printf("%d\n", i);
}
}
int main(void)
{
int val;
scanf("%d", &val);
TraverseVal(val);
return 0;
}
/*
在VSCode中的輸出結果是:
--------------------------
10
2
3
5
7
--------------------------
*/
變量的作用域和存儲方式
變量按作用域分爲全局變量
和局部變量
。
變量按變量的存儲方式分爲:靜態變量、自動變量和寄存器變量。
全局變量:在所有函數外部定義的變量叫全局變量。全局變量使用範圍:從定義位置開始到整個程序結束。
局部變量:在一個函數內部定義的變量或者函數的形參,都統稱爲局部變量。
如:
void f(int i)
{
int j= 20;
}
i
和 j
都屬於局部變量。局部變量使用範圍:只能在本函數內部使用。
注意全局變量和局部變量命名衝突的問題
在一個函數內部如果定義的局部變量的名字和全局變量名一樣時,局部變量會屏蔽掉全局變量。
常用的系統函數
系統函數 | 說明 |
---|---|
double sqrt(double s); | 求 x 的平方根 |
int abs(int x); | 求 x 的絕對值 |
double fabc(double x) | 求 x 的絕對值 |
推薦書籍 機械工業出版社《turboc 2.0實用大全》
注:遞歸(需要先理解棧),初學者可以先跳過。具體可以參看郝斌老師的數據結構視頻。
【說明】
-
本學習筆記整理自B站郝斌老師的《郝斌C語言自學教程》片段P104-P120。
-
筆記中所有代碼均在windows10操作系統,在VSCode編輯器中通過測試。具體VSCode C語言開發環境搭建方法請參照我的另一篇CSDN博客——Windows10下利用Visual Studio Code搭建C語言開發環境。
後記
如果對你有所幫助,歡迎關注我的公衆號。這個公衆號主要是慢慢分享和記錄自己學習編程的筆記,比如:C,Python,Java等。後續也會分享自己面試以及在職場上的成長心得。