110年普考程式設計概要
四、程式語言 C 可使用不同資料型別的變數存取資料與傳遞函式的參數。 #include <stdio.h> #include <stdlib.h> #include <string.h> void myFunction(int *a, int b, int *c, char *d) { c[1] = *a+b; d[*c] = d[2]; b = 17; int *r = c+1; c = a; *c = *a+1; printf("during:%s %d %d %d %d\n", &d[1], *a, b, *c, *r); } int main( ) { char animal[7] = "cat"; int x = strlen(animal); int z[3] = {1, 3, 5}; int * y = (int *)malloc(sizeof(int)*3); int *p = &x; int *q = &z[1]; q[1] = *p+10; printf("before:%s %d %d %d %d\n", animal, *z, z[1], z[2], x); myFunction(p, x, q, animal); printf("after:%s %d %d %d %d\n", animal, z[0], z[1], z[2], x); return 0; } (一)請說明上述程式執行的結果。(15分) (二)請說明比較 C 程式宣告一個陣列時,如上述程式變數 y、z,使用一般陣列變數與指標變數的異同。(5分) (三)請說明比較 C 程式語言中,函式參數傳遞方法,傳值呼叫 (call by value)與傳址呼叫 (call by address) 異同。(5分) |
答:
(一)
#include <stdio.h> #include <stdlib.h> #include <string.h> void myFunction(int *a, int b, int *c, char *d) { c[1] = *a+b; d[*c] = d[2]; b = 17; int *r = c+1; c = a; *c = *a+1; printf("during:%s %d %d %d %d\n", &d[1], *a, b, *c, *r); } int main( ) { char animal[7] = "cat"; int x = strlen(animal); int z[3] = {1, 3, 5}; int * y = (int *)malloc(sizeof(int)*3); int *p = &x; int *q = &z[1]; q[1] = *p+10; printf("before:%s %d %d %d %d\n", animal, *z, z[1], z[2], x); myFunction(p, x, q, animal); printf("after:%s %d %d %d %d\n", animal, z[0], z[1], z[2], x); return 0; } |
執行結果:
before:cat 1 3 13 3
during:att 4 17 4 6
after:catt 1 3 6 4
說明:
animal陣列:
0 |
1 |
2 |
3 |
4 |
5 |
6 |
c |
a |
t |
'\0' |
'\0' |
'\0' |
'\0' |
x變數:
3 |
p↑ |
z陣列:
0 |
1 |
2 |
1 |
3 |
5→13 |
|
q↑ |
q(1)↑ |
呼叫myFunction:
x變數:
x = b
3→17→4 |
p↑, a↑ |
z陣列:
0 |
1 |
2 |
1 |
3→4 |
5→13→6 |
|
q↑, c↑, a↑ |
q(1)↑, c(1)↑, r↑ |
animal陣列:
animal = d
0 |
1 |
2 |
3 |
4 |
5 |
6 |
c |
a |
t |
'\0'→t |
'\0' |
'\0' |
'\0' |
(二)
以下是對於在 C 語言中宣告一個陣列時,使用一般陣列變數 (如 z) 與使用指標變數 (如 y) 的異同點的說明:
1.記憶體配置:
(1)一般陣列變數:
當宣告一個陣列,記憶體會在堆疊 (stack) 上為其保留空間。這個空間的大小是固定的,而且在編譯時期就已經確定。
(2)指標變數:
當使用 malloc 或 calloc 函數為指標變數分配空間時,該空間是在堆積(heap) 上配置的。這意味著,可以在執行時動態地為它分配記憶體,而且大小是靈活的。
2.生命週期和可用性:
(1)一般陣列變數:
當變數的領域結束時,陣列所占用的記憶體將自動釋放。不能手動釋放其記憶體。
(2)指標變數:
配置在堆積上的記憶體需要手動釋放。當不再需要該記憶體時,應該使用 free 函數將其釋放,以防止記憶體洩漏。
3.靈活性:
(1)一般陣列變數:其大小是固定的,一旦宣告就不能改變。
(2)指標變數:
由於記憶體是動態分配的,可以在任何時候更改其大小 (如使用 realloc 函數)。
4.操作:
(1)可以使用相同的方式存取和操作陣列和指標變數指向的元素 (如使用下標操作)。
(2)指標提供了更多的低級操作和技巧,例如指標算術。
5.效能和安全性:
(1)因為一般陣列的大小在編譯時就已經確定,因此它可能比動態分配的記憶體更有效率。
(2)不適當的動態記憶體管理可能導致錯誤,例如記憶體洩漏或釋放後再使用,這在一般陣列中不會發生。
總之,一般陣列和指標陣列各有其用途和優勢。選擇哪一種取決於特定的需求和應用情境。
(三)
1.傳值呼叫(call by value):
(1)只提供 in mode 參數。
(2)當主程式呼叫副程式時,系統先為副程式的形式參數配置所需的記憶體,然 後將主程式的實際參數 (actual parameter) 值傳給副程式的型式參數 (formal parameter) 值。
2.傳址呼叫(call by address):
(1)提供 in out mode 參數。
(2)當主程式呼叫副程式時,將主程式的實際參數位址傳給副程式的型式參數。