struct結(jié)構(gòu)體數(shù)據(jù)類型
前言
我們知道,在C語言中有一些基本的數(shù)據(jù)類型,如charintfloatlongdoublestring(c99)
等等數(shù)據(jù)類型,他們可以表示一些事物的基本屬性,但是當我們想表達一個事物的全部或部分屬性時,這時候再用單一的基本數(shù)據(jù)類型明顯就無法滿足需求了,這時候C提供了一種自定義數(shù)據(jù)類型,他可以封裝多個基本數(shù)據(jù)類型,這種數(shù)據(jù)類型叫結(jié)構(gòu)體,英文名稱struct,可以使用struct關鍵詞聲明結(jié)構(gòu)體
結(jié)構(gòu)體的聲明
結(jié)構(gòu)體的聲明語法如下
struct [structure tag] /*結(jié)構(gòu)體的標簽*/{ member definition; /*零個或多個成員變量的定義*/ member definition; ... member definition; } [one or more structure variables]; /*一個或多個結(jié)構(gòu)體變量的定義*/
結(jié)構(gòu)體標簽(structure tag)是可選的,但是推薦還是寫上,這樣使得代碼更加規(guī)范清晰,成員變量的定義一般為基本數(shù)據(jù)類型,如int age;char name[10]等,成員變量之間使用;隔開,最后一個成員變量后面的;可選, 如下面定義一個圖書信息的結(jié)構(gòu)體變量
struct Books { char title[50]; char author[50]; char subject[100]; int book_id; } book;
如下所示
struct Books { char title[50]; char author[50]; char subject[100]; int book_id } book;
我省略了最后一個成員變量后面的分號;代碼可以正常運行,但是當我使用gcc編譯的時候,出現(xiàn)了下面信息
gcc struct.c ``` output ``` shell struct.c1: warning: no semicolon at end of struct or union } book; ^
這是警告提示,提示我們需要在struct和union數(shù)據(jù)類型定義的后面加上分號;,這樣的好處就是當我們需要再添加一個成員變量的時候,只需寫上該成員變量的定義,而無需先敲;,我太機智了,手動滑稽...
沒有成員變量的結(jié)構(gòu)體
我們也可以定義一個空的結(jié)構(gòu)體,有時候我們需要某一個結(jié)構(gòu)體數(shù)據(jù)類型,但是暫時又不知道如何填充里面的成員變量,我們可以有如下定義
struct Books { //TODO } book;
訪問結(jié)構(gòu)體成員
定義完結(jié)構(gòu)體積后接下來就是去訪問它并給他賦值,為了訪問一個結(jié)構(gòu)體成員變量,我們可以使用成員操作符(.)成員訪問運算符被編碼為結(jié)構(gòu)變量名稱和我們希望訪問的結(jié)構(gòu)成員之間的句點(.)如下所示的完整代碼
struct.c
#include #include struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; int main( ) { struct Books Book1; /* Declare Book1 of type Book */ struct Books Book2; /* Declare Book2 of type Book */ /* book 1 specification */ strcpy( Book1.title, "C Programming"); strcpy( Book1.author, "Nuha Ali"); strcpy( Book1.subject, "C Programming Tutorial"); Book1.book_id = 6495407; /* book 2 specification */ strcpy( Book2.title, "Telecom Billing"); strcpy( Book2.author, "Zara Ali"); strcpy( Book2.subject, "Telecom Billing Tutorial"); Book2.book_id = 6495700; /* print Book1 info */ printf( "Book 1 title : %sn", Book1.title); printf( "Book 1 author : %sn", Book1.author); printf( "Book 1 subject : %sn", Book1.subject); printf( "Book 1 book_id : %dn", Book1.book_id); /* print Book2 info */ printf( "Book 2 title : %sn", Book2.title); printf( "Book 2 author : %sn", Book2.author); printf( "Book 2 subject : %sn", Book2.subject); printf( "Book 2 book_id : %dn", Book2.book_id); return 0; }
編譯并執(zhí)行
gcc struct.c && ./a.out
輸出
Book 1 title : C Programming Book 1 author : Nuha Ali Book 1 subject : C Programming Tutorial Book 1 book_id : 6495407 Book 2 title : Telecom Billing Book 2 author : Zara Ali Book 2 subject : Telecom Billing Tutorial Book 2 book_id : 6495700
結(jié)構(gòu)作為函數(shù)參數(shù)
同樣的,我們也可以像基本數(shù)據(jù)類型一樣,把結(jié)構(gòu)體作為函數(shù)的參數(shù),如下所示我們定義一個打印結(jié)構(gòu)體的函數(shù)
#include #include struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; /* function declaration */ void printBook( struct Books book ); int main( ) { struct Books Book1; /* Declare Book1 of type Book */ struct Books Book2; /* Declare Book2 of type Book */ /* book 1 specification */ strcpy( Book1.title, "C Programming"); strcpy( Book1.author, "Nuha Ali"); strcpy( Book1.subject, "C Programming Tutorial"); Book1.book_id = 6495407; /* book 2 specification */ strcpy( Book2.title, "Telecom Billing"); strcpy( Book2.author, "Zara Ali"); strcpy( Book2.subject, "Telecom Billing Tutorial"); Book2.book_id = 6495700; /* print Book1 info */ printBook( Book1 ); /* Print Book2 info */ printBook( Book2 ); return 0; } void printBook( struct Books book ) { printf( "Book title : %sn", book.title); printf( "Book author : %sn", book.author); printf( "Book subject : %sn", book.subject); printf( "Book book_id : %dn", book.book_id); }
編譯運行
gcc struct.c && ./a.out
輸出
Book 1 title : C Programming Book 1 author : Nuha Ali Book 1 subject : C Programming Tutorial Book 1 book_id : 6495407 Book 2 title : Telecom Billing Book 2 author : Zara Ali Book 2 subject : Telecom Billing Tutorial Book 2 book_id : 6495700
結(jié)構(gòu)體的指針
我們也可以定義結(jié)構(gòu)體指針,像這樣
struct Books *struct_pointer;
現(xiàn)在你可以存放結(jié)構(gòu)體變量的地址在結(jié)構(gòu)體變量指針中.和基本數(shù)據(jù)類型的變量一樣,我們使用&操作符取一個變量的地址
struct_pointer = &Book1;
接下來就是使用結(jié)構(gòu)體指針去訪問成員變量了,訪問的操作符我們由原來的.變?yōu)?>,沒錯,這個是不是很形象呢?完整代碼如下
#include #include struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; /* function declaration */ void printBook( struct Books *book ); int main( ) { struct Books Book1; /* Declare Book1 of type Book */ struct Books Book2; /* Declare Book2 of type Book */ /* book 1 specification */ strcpy( Book1.title, "C Programming"); strcpy( Book1.author, "Nuha Ali"); strcpy( Book1.subject, "C Programming Tutorial"); Book1.book_id = 6495407; /* book 2 specification */ strcpy( Book2.title, "Telecom Billing"); strcpy( Book2.author, "Zara Ali"); strcpy( Book2.subject, "Telecom Billing Tutorial"); Book2.book_id = 6495700; /* print Book1 info by passing address of Book1 */ printBook( &Book1 ); /* print Book2 info by passing address of Book2 */ printBook( &Book2 ); return 0; } void printBook( struct Books *book ) { printf( "Book title : %sn", book->title); printf( "Book author : %sn", book->author); printf( "Book subject : %sn", book->subject); printf( "Book book_id : %dn", book->book_id); }
編譯運行
gcc struct.c && ./a.out
輸出
Book 1 title : C Programming Book 1 author : Nuha Ali Book 1 subject : C Programming Tutorial Book 1 book_id : 6495407 Book 2 title : Telecom Billing Book 2 author : Zara Ali Book 2 subject : Telecom Billing Tutorial Book 2 book_id : 6495700
結(jié)構(gòu)體數(shù)組
#include #include struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; /* function declaration */ void printBook( struct Books *book ); int main( ) { struct Books books[2]; /* book 1 specification */ strcpy( books[0].title, "C Programming"); strcpy( books[0].author, "Nuha Ali"); strcpy( books[0].subject, "C Programming Tutorial"); books[0].book_id = 6495407; /* book 2 specification */ strcpy( books[1].title, "Telecom Billing"); strcpy( books[1].author, "Zara Ali"); strcpy( books[1].subject, "Telecom Billing Tutorial"); books[1].book_id = 6495700; /* print Book1 info by passing address of Book1 */ printBook( &books[0] ); /* print Book2 info by passing address of Book2 */ printBook( &books[1] ); return 0; } void printBook( struct Books *book ) { printf( "Book title : %sn", book->title); printf( "Book author : %sn", book->author); printf( "Book subject : %sn", book->subject); printf( "Book book_id : %dn", book->book_id); }
編譯運行
gcc struct.c && ./a.out
輸出
Book 1 title : C Programming Book 1 author : Nuha Ali Book 1 subject : C Programming Tutorial Book 1 book_id : 6495407 Book 2 title : Telecom Billing Book 2 author : Zara Ali Book 2 subject : Telecom Billing Tutorial Book 2 book_id : 6495700
結(jié)構(gòu)體的內(nèi)存計算
沒錯,估計你已經(jīng)知道了,結(jié)構(gòu)體變量的所占用內(nèi)存空間的大小為各成員變量所占空間之和,如下所示的結(jié)構(gòu)體占用內(nèi)存大小在注釋里面
#include #include struct Books { }; int main( ) { printf("%dn", (int) sizeof(struct Books)); /*0*/ return 0; } #include #include struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; int main() { printf("%dn", (int) sizeof(struct Books)); /*204*/ return 0; }
位域
有時候我們內(nèi)存緊張的時候,我們可以使用位域定義結(jié)構(gòu)體成員變量,比如當我們需要定義一個表示true或false的時候,如果想這樣定義
int isOpen;
明顯很浪費空間,因為一個真假值只需要一個字位表示,所以我們可以這樣定義
unsigned int isOpen:1;
但是如果你直接寫在函數(shù)中是會報錯的,我們應該寫在結(jié)構(gòu)體中
int main() { unsigned int isOpen:1; /*編譯無法通過*/ return 0; }
正確姿勢
struct packed_struct { unsigned int f1:1; unsigned int f2:1; unsigned int f3:1; unsigned int f4:1; unsigned int type:4; unsigned int my_int:9; } pack;
C盡可能緊湊地自動打包上述位字段,前提是字段的最大長度小于或等于計算機的整數(shù)字長。如果不是這種情況,那么一些編譯器可能允許字段存儲器重疊,而其他編譯器會將下一個字段存儲在下一個字中。
#include #include struct packed_struct { unsigned int f1:1; unsigned int f2:1; unsigned int f3:1; unsigned int f4:1; unsigned int type:4; unsigned int my_int:9; } pack; int main() { printf("%dn", (int) sizeof(struct packed_struct)); return 0; }
輸出結(jié)果 8
審核編輯 黃宇
-
C語言
+關注
關注
180文章
7594瀏覽量
135863 -
結(jié)構(gòu)體
+關注
關注
1文章
129瀏覽量
10823
發(fā)布評論請先 登錄
相關推薦
評論