C 語言 結構-宣告、變數及指標
作者:許裕永 Darban
結構是一種 C 語言提供設計師自行開發新型別的機制,使用時機是設計師需要把一個以上的資料群組成一個單位時。假如程式中要儲存許多位學生的資料,而每一位學生都擁有學號、姓名、性別及5科成績的資料。此時,利用結構把每一位學生的資料群組成一個單位,便是相當適合的使用時機。
>_< 宣告結構
基本語法:
struct Identify
{
Members;
};
struct ->是宣告及使用結構時必要的關鍵字。
Identify ->由開發者自己取的名字,就如同變數或函式名稱。
Members ->任意個合法的型別宣告的變數、陣列或指標。
; ->結構宣告必須以 ‘;’ 結束
Example:
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
};
大括號中只接受成員的宣告,不接受指派。
>_< 結構變數
用已宣告的結構為型別宣告的變數,稱之為結構變數。
用已宣告的結構為型別宣告的變數,稱之為結構變數。
1.
宣告結構變數
A.
宣告結構後宣告
Example :
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
};
int main(int
argc, char *argv[]) {
struct Student
s,s2;
struct Student
s_array[5];
return 0;
}
如同一般型別,可以宣告變數或陣列。
B.
宣告結構時宣告
Example :
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
}t,t2,t_array[5];
可以在結構宣告敍述結束的
‘;’ 前,宣告變數名稱。
2.
指派結構變數的成員
A.
宣告結構後,宣告結構變數時指派
Example:
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
};
int main(int
argc, char *argv[]) {
struct Student s ={"S0001","Darban Hsu",1,{90,94,90,85,95}},s2;
struct Student s_array[5]={
{"S0003","
Tom Hanks ",1,{100,80,90,90,89}},
{"S0004","
Derek Jeter ",1,{90,88,95,91,80}}
};
return 0;
}
宣告變數或陣列時,以一組大括號指派一個群組的資料。資料的順序必須吻合成員的宣告順序。
B.
宣告結構時,宣告結構變數時指派
Example:
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
}t={"S0001","Darban
Hsu",1,{90,94,90,85,95}},t2,
t_array[5]={
{"S0003","
Tom Hanks ",1,{100,80,90,90,89}},
{"S0004","
Derek Jeter ",1,{90,88,95,91,80}}
};
這是合法的,是有必要把程式碼搞成這樣嗎???????
3.
存取結構變數的成員
在宣告敍述之後,可以用成員存取運算符號
‘.’ 存取結構變數的成員。
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
};
int main(int
argc, char *argv[]) {
struct Student s
={"S0001","Darban Hsu",1,{90,94,90,85,95}},s2;
struct Student s_array[5]={
{"S0003","Tom Hanks
",1,{100,80,90,90,89}},
{"S0004","Derek Jeter
",1,{90,88,95,91,80}}
};
strcpy(s2.id,"S0002");
strcpy(s2.name,"Jennifer
Aniston");
s2.sex = 0;
s2.score[0]=
99;
s2.score[1]=
89;
s2.score[2]=
79;
s2.score[3]=
98;
s2.score[4]=
96;
printf("%s->%d\n",s.name,s.score[2]);
printf("%s->%d\n",s2.name,s2.score[2]);
printf("%s->%d\n",s_array[0].name,s_array[0].score[2]);
return 0;
}
|) 在宣告敍述之外,不可以用大括號一次指派所有成員。
|) 文字不可以用 ‘=’ 指派,必須用 strcpy ,請記得 include <string.h> 。
4.
以結構變數為參數
Example A:
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
};
void showInfo(struct Student);
void showInfo(struct Student s)
{
double total=0;
int index;
for(index = 0
;index < 5; index++)
{
total
+= s.score[index];
}
printf("%s
/ %s : %.2f \n", s.id, s.name, total/5);
}
int main(int
argc, char *argv[]) {
struct Student s
={"S0001","Darban Hsu",1,{90,94,90,85,95}},s2;
struct Student s_array[5]={
{"S0003","Tom Hanks
",1,{100,80,90,90,89}},
{"S0004","Derek Jeter
",1,{90,88,95,91,80}}
};
strcpy(s2.id,"S0002");
strcpy(s2.name,"Jennifer
Aniston");
s2.sex = 0;
s2.score[0]= 99;
s2.score[1]= 89;
s2.score[2]= 79;
s2.score[3]= 98;
s2.score[4]= 96;
showInfo(s);
showInfo(s2);
return 0;
}
Example B :
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
};
void
showInfo(struct Student);
void changeScore(struct Student);
void
showInfo(struct Student s)
{
double total=0;
int index;
for(index = 0 ;index < 5; index++)
{
total += s.score[index];
}
printf("%s / %s : %.2f \n",
s.id, s.name, total/5);
}
void changeScore(struct Student s)
{
int index;
for(index = 0
;index < 5; index++)
{
s.score[index]
= 0;
}
}
int main(int
argc, char *argv[]) {
struct Student s
={"S0001","Darban Hsu",1,{90,94,90,85,95}},s2;
struct Student s_array[5]={
{"S0003","Tom Hanks
",1,{100,80,90,90,89}},
{"S0004","Derek Jeter
",1,{90,88,95,91,80}}
};
strcpy(s2.id,"S0002");
strcpy(s2.name,"Jennifer
Aniston");
s2.sex = 0;
s2.score[0]= 99;
s2.score[1]= 89;
s2.score[2]= 79;
s2.score[3]= 98;
s2.score[4]= 96;
changeScore(s);
changeScore(s2);
showInfo(s);
showInfo(s2);
return 0;
}
在 Example B 中的 changeScore 試圖要修改參數的 score 陣列的值為 0 ,結果是失敗的。因為以結構變數為參數,是傳值呼叫;也就是說執行器是複製一份 main 中的結構變數 s 的資料群組指派給 changeScore 的參數 s。所以在
changeScore 中的 s 的運算跟
main 中的 s 是無關的。
>_< 結構指標
以結構為型別宣告的指構,稱之為結構指標。
1.
宣告結構指標
A.
宣告結構後宣告
Example :
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
};
int main(int
argc, char *argv[]) {
struct Student*
s;
return 0;
}
如同一般型別,在型別後加
‘*’。
B.
宣告結構時宣告
Example :
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
}*t;
可以在結構宣告敍述結束的
‘;’ 前宣告指標名稱, ‘*’ 加在指標名稱前。
2.
動態配置記憶體空間
結構變數在宣告時,執行環境便依結構的宣告內容配置適當的記憶體空間。但指標必須透過
malloc() 動態配置,雖然多一個步驟,但可以透過 free() 釋放不需要的記憶體空間。
Example :
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
} ;
int main(int
argc, char *argv[]) {
struct Student*
pointer_s = (struct Student*)malloc(sizeof(struct Student));
struct Student*
pointer_t;;
pointer_t = (struct Student*)malloc(sizeof(struct Student));
return 0;
}
3.
存取結構變數的成員
在動態配置記憶體之後,可以用指標成員存取運算符號
‘->’ 存取結構指標的成員。
Example :
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
} ;
int main(int
argc, char *argv[]) {
struct Student* pointer_s = (struct
Student*)malloc(sizeof(struct Student));
strcpy(pointer_s->id,
"S0001");
strcpy(pointer_s->name,
"Darban Hsu");
pointer_s->sex
= 1;
pointer_s->score[0]
= 98;
pointer_s->score[1]
= 96;
pointer_s->score[2]
= 89;
pointer_s->score[3]
= 86;
pointer_s->score[4]
= 94;
printf("%s
: %s", pointer_s->id, pointer_s->name);
return 0;
}
結構指標的成員的值,不可以用大括號做一次性的指派。
4.
以結構指標為參數
Example A:
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
} ;
void showInfo(struct Student*);
void showInfo(struct Student* pointer_s)
{
double total=0;
int index;
for(index = 0
;index < 5; index++)
{
total
+= pointer_s->score[index];
}
printf("%s
/ %s : %.2f \n", pointer_s->id, pointer_s->name, total/5);
}
int main(int
argc, char *argv[]) {
struct Student* pointer_s = (struct
Student*)malloc(sizeof(struct Student));
strcpy(pointer_s->id,
"S0001");
strcpy(pointer_s->name, "Darban
Hsu");
pointer_s->sex = 1;
pointer_s->score[0] = 98;
pointer_s->score[1] = 96;
pointer_s->score[2] = 89;
pointer_s->score[3] = 86;
pointer_s->score[4] = 94;
showInfo(pointer_s);
return 0;
}
Example B :
struct Student
{
char id[6];
char name[21];
int sex;
int score[5];
} ;
void
showInfo(struct Student*);
void changeScore(struct Student*);
void
showInfo(struct Student* pointer_s)
{
double total=0;
int index;
for(index = 0 ;index < 5; index++)
{
total +=
pointer_s->score[index];
}
printf("%s / %s : %.2f \n",
pointer_s->id, pointer_s->name, total/5);
}
void changeScore(struct Student* pointer_s)
{
int index;
for(index = 0
;index < 5; index++)
{
pointer_s->score[index]
= 0;
}
}
int main(int
argc, char *argv[]) {
struct Student* pointer_s = (struct
Student*)malloc(sizeof(struct Student));
strcpy(pointer_s->id,
"S0001");
strcpy(pointer_s->name, "Darban
Hsu");
pointer_s->sex = 1;
pointer_s->score[0] = 98;
pointer_s->score[1] = 96;
pointer_s->score[2] = 89;
pointer_s->score[3] = 86;
pointer_s->score[4] = 94;
changeScore(pointer_s);
showInfo(pointer_s);
return 0;
}
在 Example B 中的 changeScore 成功的修改了參數的 score 陣列的值為 0。因為以結構指標為參數,是傳址呼叫;也就是說執行器是複製一份 main 中的結構指標 pointer_s 儲存的記憶體位址,指派給 changeScore 的參數 pointer_s 。所以在 changeScore 中的pointer_s
跟 main 中的pointer_s 是存取的是同一群資料群組 ( 記憶體叢集
)。
在開發大型專案時,妥善的利用結構指標,可以避免大量資料的複製,有效的活用記憶體。
沒有留言:
張貼留言