struct結(jié)構(gòu)體數(shù)據(jù)類型
前言
我們知道,在C語(yǔ)言中有一些基本的數(shù)據(jù)類型,如charintfloatlongdoublestring(c99)
等等數(shù)據(jù)類型,他們可以表示一些事物的基本屬性,但是當(dāng)我們想表達(dá)一個(gè)事物的全部或部分屬性時(shí),這時(shí)候再用單一的基本數(shù)據(jù)類型明顯就無(wú)法滿足需求了,這時(shí)候C提供了一種自定義數(shù)據(jù)類型,他可以封裝多個(gè)基本數(shù)據(jù)類型,這種數(shù)據(jù)類型叫結(jié)構(gòu)體,英文名稱struct,可以使用struct關(guān)鍵詞聲明結(jié)構(gòu)體
結(jié)構(gòu)體的聲明
結(jié)構(gòu)體的聲明語(yǔ)法如下
struct [structure tag] /*結(jié)構(gòu)體的標(biāo)簽*/{ member definition; /*零個(gè)或多個(gè)成員變量的定義*/ member definition; ... member definition; } [one or more structure variables]; /*一個(gè)或多個(gè)結(jié)構(gòu)體變量的定義*/
結(jié)構(gòu)體標(biāo)簽(structure tag)是可選的,但是推薦還是寫上,這樣使得代碼更加規(guī)范清晰,成員變量的定義一般為基本數(shù)據(jù)類型,如int age;char name[10]等,成員變量之間使用;隔開(kāi),最后一個(gè)成員變量后面的;可選, 如下面定義一個(gè)圖書信息的結(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;
我省略了最后一個(gè)成員變量后面的分號(hào);代碼可以正常運(yùn)行,但是當(dāng)我使用gcc編譯的時(shí)候,出現(xiàn)了下面信息
gcc struct.c ``` output ``` shell struct.c1: warning: no semicolon at end of struct or union } book; ^
這是警告提示,提示我們需要在struct和union數(shù)據(jù)類型定義的后面加上分號(hào);,這樣的好處就是當(dāng)我們需要再添加一個(gè)成員變量的時(shí)候,只需寫上該成員變量的定義,而無(wú)需先敲;,我太機(jī)智了,手動(dòng)滑稽...
沒(méi)有成員變量的結(jié)構(gòu)體
我們也可以定義一個(gè)空的結(jié)構(gòu)體,有時(shí)候我們需要某一個(gè)結(jié)構(gòu)體數(shù)據(jù)類型,但是暫時(shí)又不知道如何填充里面的成員變量,我們可以有如下定義
struct Books {
//TODO
} book;
訪問(wèn)結(jié)構(gòu)體成員
定義完結(jié)構(gòu)體積后接下來(lái)就是去訪問(wèn)它并給他賦值,為了訪問(wèn)一個(gè)結(jié)構(gòu)體成員變量,我們可以使用成員操作符(.)成員訪問(wèn)運(yùn)算符被編碼為結(jié)構(gòu)變量名稱和我們希望訪問(wèn)的結(jié)構(gòu)成員之間的句點(diǎn)(.)如下所示的完整代碼
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ù),如下所示我們定義一個(gè)打印結(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);
}
編譯運(yùn)行
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ù)類型的變量一樣,我們使用&操作符取一個(gè)變量的地址
struct_pointer = &Book1;
接下來(lái)就是使用結(jié)構(gòu)體指針去訪問(wèn)成員變量了,訪問(wèn)的操作符我們由原來(lái)的.變?yōu)?>,沒(méi)錯(cuò),這個(gè)是不是很形象呢?完整代碼如下
#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);
}
編譯運(yùn)行
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);
}
編譯運(yùn)行
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ì)算
沒(méi)錯(cuò),估計(jì)你已經(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;
}
位域
有時(shí)候我們內(nèi)存緊張的時(shí)候,我們可以使用位域定義結(jié)構(gòu)體成員變量,比如當(dāng)我們需要定義一個(gè)表示true或false的時(shí)候,如果想這樣定義
int isOpen;
明顯很浪費(fèi)空間,因?yàn)橐粋€(gè)真假值只需要一個(gè)字位表示,所以我們可以這樣定義
unsigned int isOpen:1;
但是如果你直接寫在函數(shù)中是會(huì)報(bào)錯(cuò)的,我們應(yīng)該寫在結(jié)構(gòu)體中
int main() {
unsigned int isOpen:1; /*編譯無(wú)法通過(guò)*/
return 0;
}
正確姿勢(shì)
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盡可能緊湊地自動(dòng)打包上述位字段,前提是字段的最大長(zhǎng)度小于或等于計(jì)算機(jī)的整數(shù)字長(zhǎng)。如果不是這種情況,那么一些編譯器可能允許字段存儲(chǔ)器重疊,而其他編譯器會(huì)將下一個(gè)字段存儲(chǔ)在下一個(gè)字中。
#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語(yǔ)言
+關(guān)注
關(guān)注
183文章
7644瀏覽量
145576 -
結(jié)構(gòu)體
+關(guān)注
關(guān)注
1文章
131瀏覽量
11372
發(fā)布評(píng)論請(qǐng)先 登錄
C語(yǔ)言結(jié)構(gòu)體對(duì)齊介紹
C語(yǔ)言中數(shù)組和結(jié)構(gòu)體的內(nèi)存表示和布局
C語(yǔ)言結(jié)構(gòu)體使用
詳細(xì)講解c語(yǔ)言enum枚舉類型
漫談C語(yǔ)言結(jié)構(gòu)體
【干貨】c語(yǔ)言基礎(chǔ)語(yǔ)法——結(jié)構(gòu)體
結(jié)構(gòu)體的相關(guān)資料下載
怎樣去使用C語(yǔ)言的結(jié)構(gòu)體和共用體呢
c語(yǔ)言_結(jié)構(gòu)體和共同體
C語(yǔ)言程序設(shè)計(jì)教程之選擇結(jié)構(gòu)的資料講解
C語(yǔ)言程序設(shè)計(jì)教程之結(jié)構(gòu)體與共用體的詳細(xì)資料說(shuō)明
干貨|手把手教你寫單片機(jī)的C語(yǔ)言結(jié)構(gòu)體
C語(yǔ)言結(jié)構(gòu)體史上最詳細(xì)的講解【軟件干貨】
評(píng)論