Like Share Discussion Bookmark Smile

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

C語言 - 第三十二章 | struct - 結構與指標

結構與指標

示範了如何宣告struct指標,以及如何使用&struct實例取位址值,如果使用struct的指標來存取其成員,則必須使用->運算子。

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

struct Ball {
char color[10];
double radius;
};

int main() {

struct Ball ball = {"red", 4.0};
struct Ball *ptr;
ptr = &ball;

printf("ball: %s\t%.2f\n", ptr->color, ptr->radius);

return 0;
}
1
2
// 執行結果
ball: red 4.00


C語言 - 第三十一章 | struct - struct 簡介 說過,如果要將struct實例作為引數傳遞,則會直接進行成員值的複製,如果並不想要複製實例,可以直接傳遞struct實例的位址值。

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

struct Ball {
char color[10];
double radius;
};

void show(struct Ball *ball);

int main() {

struct Ball ball = {"red", 4.0};

show(&ball);

return 0;
}

void show(struct Ball *ball) {
printf("ball: %s\t%.2f\n", ball->color, ball->radius);
}
1
2
// 執行結果
ball: red 4.00

想要傳遞struct實例的位址值,一是情況是函式想改變的是被傳遞的struct實例本身,而不是實例的複本,另一個情況效率考量,如果 struct實例本身很龐大,若不想有複製整個struct實例負擔時,也可採用傳遞struct實例位址值的方式。


注意到,以下的語法取得的是struct實例的成員位址值,而不是struct實例的位址值。

1
2
struct Ball ball = {"red", 4.0};
printf("%p\n", &ball.color);

為了避免誤會,建議加上括號比較清楚。

1
2
struct Ball ball = {"red", 4.0};
printf("%p\n", &(ball.color));

類似的,如果ptrstruct的指標,並儲存某個實例的位址值,那麼以下取得的是實例的成員位址值,而不是實例的位址值,建議還是如第二行的,加上括號比較清楚。

1
2
printf("%p\n", &ptr->color);
printf("%p\n", &(ptr->color));

下面這個例子是個比較進階的例子,程式中使用 函式指標,讓struct實例擁有可操作的函式,而在操作struct實例擁有的函式時,傳入實例的位址值,如此該函式可以取得實例成員值並進行運算,這是在模擬物件導向中,物件實例擁有屬性及方法(method)的特性。

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
#include <stdio.h>
#include <stdlib.h>

typedef struct Ball {
char *color;
double radius;
double (*volumn)(struct Ball*); // 函式指標
} Ball;

// 計算實例體積
double volumn(Ball *this) {
double r = this->radius; // 模擬 this 指標 的行為
return r * r * 3.14;
}

Ball* new_ball(char *color, double radius) {
Ball *ball = (Ball*) malloc(sizeof(Ball));
ball->volumn = volumn; // 連結函式
ball->color = color;
ball->radius = radius;
return ball;
}

int main() {
Ball *ball = new_ball("red", 5.0);
printf("ball 實例的體積: %.2f\n", ball->volumn(ball));

return 0;
}
1
2
// 執行結果
ball 實例的體積: 78.50


struct指標的應用之一,可以參考堆疊 - 使用鏈結實作(C 語言動態記憶體宣告)佇列 - 使用鏈結實作(C語言動態記憶體宣告),當中的鏈結資料結構,就使用struct指標來連結下一個節點實例。


註:以上參考了
結構與指標
佇列 - 使用鏈結實作(C語言動態記憶體宣告)
堆疊 - 使用鏈結實作(C 語言動態記憶體宣告)