struct結構體數據類型
前言
我們知道,在C語言中有一些基本的數據類型,如charintfloatlongdoublestring(c99)
等等數據類型,他們可以表示一些事物的基本屬性,但是當我們想表達一個事物的全部或部分屬性時,這時候再用單一的基本數據類型明顯就無法滿足需求了,這時候C提供了一種自定義數據類型,他可以封裝多個基本數據類型,這種數據類型叫結構體,英文名稱struct,可以使用struct關鍵詞聲明結構體
結構體的聲明
結構體的聲明語法如下
struct [structure tag] /*結構體的標簽*/{ member definition; /*零個或多個成員變量的定義*/ member definition; ... member definition; } [one or more structure variables]; /*一個或多個結構體變量的定義*/
結構體標簽(structure tag)是可選的,但是推薦還是寫上,這樣使得代碼更加規(guī)范清晰,成員變量的定義一般為基本數據類型,如int age;char name[10]等,成員變量之間使用;隔開,最后一個成員變量后面的;可選, 如下面定義一個圖書信息的結構體變量
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數據類型定義的后面加上分號;,這樣的好處就是當我們需要再添加一個成員變量的時候,只需寫上該成員變量的定義,而無需先敲;,我太機智了,手動滑稽...
沒有成員變量的結構體
我們也可以定義一個空的結構體,有時候我們需要某一個結構體數據類型,但是暫時又不知道如何填充里面的成員變量,我們可以有如下定義
struct Books {
//TODO
} book;
訪問結構體成員
定義完結構體積后接下來就是去訪問它并給他賦值,為了訪問一個結構體成員變量,我們可以使用成員操作符(.)成員訪問運算符被編碼為結構變量名稱和我們希望訪問的結構成員之間的句點(.)如下所示的完整代碼
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
結構作為函數參數
同樣的,我們也可以像基本數據類型一樣,把結構體作為函數的參數,如下所示我們定義一個打印結構體的函數
#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
結構體的指針
我們也可以定義結構體指針,像這樣
struct Books *struct_pointer;
現(xiàn)在你可以存放結構體變量的地址在結構體變量指針中.和基本數據類型的變量一樣,我們使用&操作符取一個變量的地址
struct_pointer = &Book1;
接下來就是使用結構體指針去訪問成員變量了,訪問的操作符我們由原來的.變?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
結構體數組
#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
結構體的內存計算
沒錯,估計你已經知道了,結構體變量的所占用內存空間的大小為各成員變量所占空間之和,如下所示的結構體占用內存大小在注釋里面
#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;
}
位域
有時候我們內存緊張的時候,我們可以使用位域定義結構體成員變量,比如當我們需要定義一個表示true或false的時候,如果想這樣定義
int isOpen;
明顯很浪費空間,因為一個真假值只需要一個字位表示,所以我們可以這樣定義
unsigned int isOpen:1;
但是如果你直接寫在函數中是會報錯的,我們應該寫在結構體中
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盡可能緊湊地自動打包上述位字段,前提是字段的最大長度小于或等于計算機的整數字長。如果不是這種情況,那么一些編譯器可能允許字段存儲器重疊,而其他編譯器會將下一個字段存儲在下一個字中。
#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;
}
輸出結果 8
審核編輯 黃宇
-
C語言
+關注
關注
183文章
7642瀏覽量
144530 -
結構體
+關注
關注
1文章
131瀏覽量
11296
發(fā)布評論請先 登錄
【干貨】c語言基礎語法——結構體
結構體的相關資料下載
c語言_結構體和共同體
C語言程序設計教程之選擇結構的資料講解

C語言結構體史上最詳細的講解【軟件干貨】
評論