本篇敘述簡單的函式宣告、函式呼叫、scope
不考慮template,overload
說明之前要先了解global和local的區別,簡單來說就是在函式裡面是local,最外面的是global
#include <stdio.h>
// global
int main()
{
// local
}
// global
函式宣告
與一些程式語言不同,c/c++函式需要宣告在global區
(好像c++11開始有別的寫法?lambda/closure)
一個函式可以大致可分成以下部分:
- 額外的head (呼叫上沒問題,且維護不會造成不便的話,可省)
- 回傳型別
- 函式名
- 參數(包含型別及名稱)
- body (執行這個函式要做的事情, 包含return)
/* 假設: R式回傳型別, N是函式名, Dn是參數型別, dn是參數名稱, C是body */
R N(D1 d1, D2 d2, ...); // head, 注意後面有個分號
R N(D1 d1, D2 d2, ...)
{
C
}
例如宣告一個將int陣列數值加總的函式:
int sum(int arr[],int length);
int sum(int arr[],int length)
{
int returnValue=0;
for(int x=0;x<length;x++) returnValue+=arr[x];
return returnValue;
}
函式呼叫
比如說在main裡面呼叫剛剛的sum
int main()
{
int arr[]={1,2,3,4};
int arrLength=sizeof(arr)/sizeof(arr[0]); // sizeof很好用的
printf("%d\n",sum(arr,arrLength));
}
scope
意思是說某個變數(或函式)名字是對應哪個區裡面的變數(或函式)
可能這樣說不是很懂,可以看看下方範例
#include <stdio.h>
int a=0;
void setGlobal(int value)
{
a=value;
return; // void函式為形態,且為函式的最後一道指令,則可省略
}
int getGlobal(){ return a; }
int main()
{
printf("%d %d\n", a, getGlobal() );
// 在main,getGlobal裡面找a這個東西找不到,改找global
a=1;
printf("%d %d\n", a, getGlobal() ); // 在main裡面找a這個東西找不到,改找global,因此 a=1; 是改到global的a
setGlobal(2);
printf("%d %d\n", a, getGlobal() );
// 在setGlobal,getGlobal裡面找a這個東西找不到,改找global,因此 a=value; 改到global的a
int a=3;
printf("%d %d\n", a, getGlobal() );
// 在main裡面找到a,因此在main裡面使用a會得到main裡面的a
// 在getGlobal裡面找a這個東西找不到,改找global
a=4; setGlobal(5);
printf("%d %d\n", a, getGlobal() ); // 在main裡面找到a,因此在main裡面使用a會得到main裡面的a,因此 a=4; 改到main的a
// 在setGlobal,getGlobal裡面找a這個東西找不到,改找global
}
以上是不同函式使用相同名稱變數的情況,
那麼同樣的函式在不同層使用相同變數呢?甚麼意思?
遞迴
例如這個印出0到N的函式:(N<0甚麼都沒有)
#include <stdio.h>
void printfZeroToN(int n)
{
int N=n;
if(N<0) return;
printfZeroToN(N-1);
printf("%d\n",N);
}
每次呼叫printfZeroToN (包含在printfZeroToN裡面呼叫的printfZeroToN) 都會(依照宣告)產生新的local變數(這裡包含N和n),不會改到前一次的
想當初聽遞迴聽不懂,不過我也覺得我這樣講也不是很懂(?)有錯誤的話趕緊指出,我會盡快修正