### 函數
定義:函數是一組一起執行一個任務的語句,每個C程序至少有一個函數,即主函數main(),所有簡單的程序都可以定義其他額外的函數。
C 語言中的函數定義的一般形式如下
~~~
return_type function_name( parameter list )
{
body of the function
}
~~~
在 C 語言中,函數由一個函數頭和一個函數主體組成。下面列出一個函數的所有組成部分:
* **返回類型:**一個函數可以返回一個值。**return\_type**是函數返回的值的數據類型。有些函數執行所需的操作而不返回值,在這種情況下,return\_type 是關鍵字**void**。
* **函數名稱**:這是函數的實際名稱。函數名和參數列表一起構成了函數簽名。
* **參數**:參數就像是占位符。當函數被調用時,您向參數傳遞一個值,這個值被稱為實際參數。參數列表包括函數參數的類型、順序、數量。參數是可選的,也就是說,函數可能不包含參數。
* **函數主體**:函數主體包含一組定義函數執行任務的語句
### 調用函數
創建 C 函數時,會定義函數做什么,然后通過調用函數來完成已定義的任務。
當程序調用函數時,程序控制權會轉移給被調用的函數。被調用的函數執行已定義的任務,當函數的返回語句被執行時,或到達函數的結束括號時,會把程序控制權交還給主程序。
調用函數時,傳遞所需參數,如果函數返回一個值,則可以存儲返回值。例如:
```
#include <stdio.h>
/* 函數聲明 */
int max(int num1, int num2);
int main ()
{
/* 局部變量定義 */
int a = 100;
int b = 200;
int ret;
/* 調用函數來獲取最大值 */
ret = max(a, b);
printf( "Max value is : %d\n", ret );
return 0;
}
/* 函數返回兩個數中較大的那個數 */
int max(int num1, int num2)
{
/* 局部變量聲明 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
```
把 max() 函數和 main() 函數放一塊,編譯源代碼。當運行最后的可執行文件時,會產生下列結果:
~~~
Max value is : 200
~~~
* [ ] **知識點:函數調用時需注意先后函數存在的先后順序**
比如A函數調用B函數,則B函數的聲明一定要在A函數的前面,否則會出現報錯:B函數找不到標識符。
如正常代碼如下:
```
#include "stdafx.h"
#include <iostream>
int func(void)
{
printf("函數");
return -1;
}
int func(void* pathName, int a)
{
printf("函數");
return -1;
}
int main()
{
func();
}
```
如果我們將func函數移到main函數后面,即
```
#include "stdafx.h"
#include <iostream>
int main()
{
func();
}
int func(void)
{
printf("函數");
return -1;
}
int func(void* pathName, int a)
{
printf("函數");
return -1;
}
```
運行就會報錯如下:

原因如下:在C語言里面,程序加載過程是由上至下來進行加載,到加載到main函數時沒有找到func函數(此時func函數還沒有被加載到內存,會認為func函數沒有,不存在),而Java中為啥可以呢?因為Java是面向對象的,它對于整個class文件,會整個加載到內存,它不會分為上下。
* [ ] **為什么C語言這樣設計?**
因為C語言是以函數為基礎,它不像Java一樣以類為基礎,類作為一個對象,所有的方法都可以寫在類中。C程序是以每一個函數組成的,當設計一個應用程序之后,它會產生很高的耦合,所以C語言中的眾多的頭文件就相當于每一個接口,這些頭文件不會參與編譯,真正參與編譯的是這些頭文件實現的C文件,頭文件的存在就是為了解決程序的耦合問題。
* [ ] **解決方案**:
* 第一種方案就是,將func定義在main函數前面,就是剛開始正確的代碼
* 第二種方案就是,編寫頭文件,將func函數聲明在該頭文件中,切記只有函數的聲明,沒有函數的實現,類似于Java中的接口,具體步驟:右面解決方案資源管理器中找到源文件,右鍵,添加,新建項,如圖所示


func.h如下
```
int func(void);
int func(void* pathName, int a);
```
引用頭文件如下:

**注意:如果是自定義的頭文件,是雙引號,系統的自帶的頭文件則是尖括號**
* [ ] **#include 指令**
`#include`指令主要有兩種書寫格式. 第一種格式用于屬于C語言自身庫的頭文件:
```
[#include指令(格式1)] #include <文件名>
```
第二種格式用于所有其他頭文件,也包含任何自己編寫的文件:
```
[#include指令(格式2)] #include "文件名"
```
這兩種格式間的細微差異在于編譯器定位頭文件的方式。下面是大多數編譯器遵循的規則。
* `#include <文件名>`:搜尋系統頭文件所在的目錄(或多個目錄)。(例如,在UNIX系統中,通常把系統頭文件保存在目錄/usr/include中。)
* `#include "文件名"`:先搜尋當前目錄,然后搜尋系統頭文件所在的目錄(或多個目錄),通常可以改變搜尋頭文件的位置,這種改變經常利用諸如-I路徑這樣的命令選項來實現。
這樣如下代碼
```
#include "stdafx.h"
#include <iostream>
#include "func.h"
int main()
{
func();
}
int func(void)
{
printf("函數");
return -1;
}
int func(void* pathName, int a)
{
printf("函數");
return -1;
}
```
再次運行就不會報錯