看了三天結構體,是時候總結一下了。
關於結構體的聲明:
struct Student { char name[20]; char sex; int age; char addr[40]; }; /*然后定義一個Student 類型的 student變量*/ struct Student student;
也許是我受了Java影響,我一度寫成這樣:
struct man { int age = 30; int score = 80; }; int main() { man man1 = {20,70}; }
結果是鐵定編譯通過不了的。因為這是我自創的聲明帶默認值的結構體,編譯器沒見過。結構體成員變量在聲明中是不能賦值的。
正確的寫法是:
struct Man { int age; //這樣就好了 int score; }; int main() { struct Man man1 = {30,80}; }
定義結構體的時候每次都要寫struct 顯然是煩瑣了,精煉的C語言用來typedef來方便定義使用:
typedef struct Man { int age; int score; }man; int main() { man man1 = {20,80}; man man2 = {30,70}; man man3 = {40,99}; printf("%d\n",man1.age); printf("%d\n",man3.score); }
這樣一來大家想召喚多少個“男人”都沒有問題。另外有一個極端一點的問題,聲明結構體名和定義結構體變量名能不能一樣?我們可以試試看:
typedef struct man { int age; int score; }man; //還叫man,有意見么? int main() { man man = {40,50};//還叫man,有問題么? printf("%d\t%d\n",man.age,man.score); }
編譯運行都是沒有問題的。不信自己去試試看。
然后我們來討論重點吧:
struct Student { char name[20]; char sex; int age; char addr[40]; }; /*然后定義一個Student 類型的 student變量*/ struct Student student;
給定義的結構中name和age賦值, 可以用下面語句:
strcpy(student->name, "jack");
student->age=21;
student->name就是(*student).name的縮寫形式。
需要指出的是結構指針是指向結構的一個指針, 是結構中第一個成員的首地址, 因此在使用之前應該對結構指針初始化, 即分配整個結構長度的字節空間, 這可用下面函數完成, 仍以上例來說明如下:
student=(struct string*)malloc(size of (struct string));
size of (struct string)自動求取string結構的字節長度, malloc() 函數定義了一個大小為結構長度的內存區域, 然后將其詐地址作為結構指針返回。
注意:
結構變量名不是指向該結構的地址, 這與數組名的含義不同, 因此若需要求結構中第一個成員的首地址應該是&[結構變量名]。
聯合體
聯合體的結構定義和結構體大體相似。
當一個聯合被說明時, 編譯程序自動地產生一個變量, 其長度為聯合中最大的變量長度。
聯合既可以出現在結構內, 它的成員也可以是結構。
例如:
struct{ int age; char *addr; union{ int i; char *ch; }x; }y[10];
若要訪問結構變量y[1]中聯合x的成員i, 可以寫成:
y[1].x.i;
若要訪問結構變量y[2]中聯合x的字符串指針ch的第一個字符可寫成:
*y[2].x.ch;
若寫成"y[2].x.*ch;"是錯誤的。值得指出的是此時的*y[2].x.ch是一個沒有分配內存地址的野指針,直接賦值給它在運行時會崩潰。
結構和聯合都是由多個不同的數據類型成員組成, 但在任何同一時刻, 聯合中只存放了一個被選中的成員, 而結構的所有成員都存在。
對於聯合的不同成員賦值, 將會對其它成員重寫, 原來成員的值就不存在了, 而對於結構的不同成員賦值是互不影響的。
下面舉一個例了來加對深聯合的理解。
int main() { union{ /*定義一個聯合*/ int i; struct{ /*在聯合中定義一個結構*/ char first; char second; }half; }number; number.i=0x4241; /*聯合成員賦值*/ printf("%c%c\n", number.half.first, mumber.half.second); number.half.first='a'; /*聯合中結構成員賦值*/ number.half.second='b'; printf("%x\n", number.i); }
輸出結果為:
AB
6261
從上例結果可以看出: 當給i賦值后, 其低八位也就是first和second的值; 當給first和second賦字符后, 這兩個字符的ASCII碼也將作為i 的低八位。
用結構體寫一個單鏈表的雛形
#include <stdio.h> struct node { struct node *link; int value; }; void main() { struct node node1, node2, node3; struct node *head; //定義鏈表頭指針 node1.value = 5; //定義各個節點的內部屬性值 node2.value = 10; node3.value = 15; head = &node1; //頭指針指向第一個節點的地址 node1.link = &node2;//第一個節點的指針指向第二個節點的地址 node2.link = &node3;//第二個節點的指針鏈接到第三個節點的地址 node3.link = NULL; //第三個節點的地址為空 /*打印輸出*/ struct node *p; p = head; while(p != NULL) { printf("%d\n", p->value); p = p->link;//移動指針到下一個節點 } }
之所以說它是一個單鏈表的雛形,因為他是在是太不完整了,但是至少他已經有單鏈表的影子了。我將慢慢完善改進它。
總結給自己看的,所以整理了我認為重要的部分。