Like Share Discussion Bookmark Smile

J.J. Huang   2019-11-18   C C 語言技術 <201910>   瀏覽次數:次   DMCA.com Protection Status

C語言 - 第二十五章 | 函式入門 - 引數傳遞、傳回值

引數傳遞

引數傳遞時的傳值就是傳送(變數)值給函式上對應的參數,值被複製一份給參數,傳遞者與接受者兩個變數彼此各佔有一個記憶體,互不相干。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main() {

int x = 10;

printf("%d\n", increment(x));
printf("%d\n", x);

return 0;
}

int increment(int n) {
n = n + 1;

return n;
}

在這個程式片段中,x將值傳遞給increment()函式的參數nn雖然作了遞增運算,但是對x的儲存值並無影響,x最後仍是顯示 10


另外在傳值應用上,也可以將變數的記憶體位址值取出,傳遞位址值給指定的指標參數,只要使用&運算子就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main() {

int x = 10;

printf("%d\n", increment(&x));
printf("%d\n", x);

return 0;
}

int increment(int *n) {
*n = *n + 1;

return *n;
}

在這個程式中,increment()上的參數n是個指標,在呼叫increment()函式時,你使用取址運算子&x變數的記憶體位址取出並傳遞給指標n,而在函式中,你使用取值運算子*取出這塊記憶體位址的值,並作遞增動作之後再指定回該記憶體位址,所以程式最後的x變數會顯示值11


傳回值

在函式上宣告指標參數的目的,通常目的是若作為引數的變數值同一位址上,在函式中若有變動該位址上的值時,呼叫者也可以保留這份變動的結果,這可以解決一個問題,在C中我們在呼叫函式後只能傳回(return)一個值,若在呼叫函式時,希望能取得兩個以上的運算結果,就可以使用指標參數。

在定義函式時,一定要定義函式的傳回值型態,如果函式不傳回值,則使用void表示不傳回任何數值;一旦指定函式的傳回值不為void,則在函式中一定要使用return傳回一個數值,否則編譯器將回報錯誤。

在之前的範例中,只是使用傳值的方式傳回函式的執行結果,事實上也可以傳回一個指標或是參考,傳回指標通常意味著要對這個指標所指向的記憶體位置作取值或更動的動作,例如下面的程式中,在函式中動態建立一個陣列,並傳回它的指標值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <stdlib.h>

int* create_array(int, int);
void delete_array(int*);

int main() {

int size = 0;

printf("陣列大小: ");
scanf("%d", &size);

int *arr = create_array(size, 0);

for(int i = 0; i < size; i++) {
arr[i] = i;
}

for(int i = 0; i < size; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}

delete_array(arr);

return 0;
}

// 傳回建立的陣列位址
int* create_array(int size, int init) {

int *arr = malloc(size * sizeof(int));
for(int i = 0; i < size; i++) {
arr[i] = init;
}

return arr;
}

void delete_array(int* arr) {
free(arr);
}
1
2
3
4
5
6
7
// 執行結果
陣列大小: 5
arr[0] = 0
arr[1] = 1
arr[2] = 2
arr[3] = 3
arr[4] = 4

由於使用動態配置的方式,在使用free()之前,這塊被配置的記憶體並不會自動清除,可以直接傳回給呼叫函式的主函式,如果不是使用 malloc()來配置,則在副函式中宣告的變數記憶體,在函式執行結束後都會自動消失,傳回指標值也就沒有意義,也會造成存取錯誤,因為該塊記憶體在函式執行完畢後已經自動回收了。

在這邊的範例,也看到了如何傳遞陣列給函式,以及如何傳回一個陣列,在C中傳遞陣列或傳回陣列,一律使用傳遞記憶體位址的方法,因為陣列名稱本身就是個指標,儲存有位址資訊。

必須注意的是,函式中的區域變數在函式開始時被配置,在函式結束後,佔有的記憶體位址也會被清除,絕對不要傳回一個區域變數的位址給呼叫者,因為存取的記憶體位址中資料是未知的,所以結果是不可預期的。


註:以上參考了
引數傳遞、傳回值