C語(yǔ)言中的結(jié)構(gòu)體的入門(mén)學(xué)習(xí)教程
C語(yǔ)言中數(shù)組允許定義類型的變量,可容納相同類型的多個(gè)數(shù)據(jù)項(xiàng),但結(jié)構(gòu)體在C語(yǔ)言編程中,它允許定義不同種類的數(shù)據(jù)項(xiàng)可供其他用戶定義的數(shù)據(jù)類型。
結(jié)構(gòu)是用來(lái)代表一個(gè)記錄,假設(shè)要跟蹤圖書(shū)館的書(shū)籍??赡芤櫽嘘P(guān)每本書(shū)以下屬性:
- Title - 標(biāo)題
- Author - 作者
- Subject - 科目
- Book ID - 編號(hào)
定義結(jié)構(gòu)體
定義一個(gè)結(jié)構(gòu)體,必須使用結(jié)構(gòu)體的struct語(yǔ)句。該struct語(yǔ)句定義了一個(gè)新的數(shù)據(jù)類型,程序不止一個(gè)成員。struct語(yǔ)句的格式是這樣的:
struct [structure tag]
{
member definition;
member definition;
...
member definition;
} [one or more structure variables];
結(jié)構(gòu)體(structure)標(biāo)簽是可選的,每個(gè)成員的定義是一個(gè)正常的變量定義,如 int i; 或 float f; 或任何其他有效的變量的定義。在結(jié)構(gòu)的定義的結(jié)尾,最后的分號(hào)之前,可以指定一個(gè)或多個(gè)結(jié)構(gòu)變量,但它是可選的。這里是聲明書(shū)(Book)的結(jié)構(gòu)方式:
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
訪問(wèn)結(jié)構(gòu)體成員
要訪問(wèn)結(jié)構(gòu)體的任何成員,我們使用成員訪問(wèn)運(yùn)算符(.)成員訪問(wèn)運(yùn)算符是編碼作為結(jié)構(gòu)體變量名,并且希望訪問(wèn)結(jié)構(gòu)體部件。使用struct關(guān)鍵字來(lái)定義結(jié)構(gòu)體類型的變量。以下為例子來(lái)解釋結(jié)構(gòu)的用法:
#include <stdio.h>
#include <string.h>
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 : %s
", Book1.title);
printf( "Book 1 author : %s
", Book1.author);
printf( "Book 1 subject : %s
", Book1.subject);
printf( "Book 1 book_id : %d
", Book1.book_id);
/* print Book2 info */
printf( "Book 2 title : %s
", Book2.title);
printf( "Book 2 author : %s
", Book2.author);
printf( "Book 2 subject : %s
", Book2.subject);
printf( "Book 2 book_id : %d
", Book2.book_id);
return 0;
}
讓我們編譯和運(yùn)行上面的程序,這將產(chǎn)生以下結(jié)果:
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ù)
可以傳遞一個(gè)結(jié)構(gòu)作為函數(shù)的參數(shù),非常類似傳遞任何其他變量或指針。訪問(wèn)可以象在上面的例子已經(jīng)訪問(wèn)類似結(jié)構(gòu)變量的方式:
#include <stdio.h>
#include <string.h>
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 : %s
", book.title);
printf( "Book author : %s
", book.author);
printf( "Book subject : %s
", book.subject);
printf( "Book book_id : %d
", book.book_id);
}
讓我們編譯和運(yùn)行上面的程序,這將產(chǎn)生以下結(jié)果:
Book title : C Programming Book author : Nuha Ali Book subject : C Programming Tutorial Book book_id : 6495407 Book title : Telecom Billing Book author : Zara Ali Book subject : Telecom Billing Tutorial Book book_id : 6495700
指針結(jié)構(gòu)
非常相似定義指針結(jié)構(gòu),來(lái)定義指向任何其他變量,如下所示:
struct Books *struct_yiibaier;
現(xiàn)在,可以存儲(chǔ)結(jié)構(gòu)變量的地址在上面定義的指針變量。為了找到一個(gè)結(jié)構(gòu)變量的地址,將使用運(yùn)算符&在結(jié)構(gòu)體的名字之前,如下所示:
struct_yiibaier = &Book1;
訪問(wèn)使用一個(gè)指向結(jié)構(gòu)的結(jié)構(gòu)的成員,必須使用 -> 運(yùn)算符如下:
struct_yiibaier->title;
讓我們重新寫(xiě)上面的例子中使用結(jié)構(gòu)指針,希望這將能夠讓我們更容易地理解概念:
#include <stdio.h>
#include <string.h>
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 : %s
", book->title);
printf( "Book author : %s
", book->author);
printf( "Book subject : %s
", book->subject);
printf( "Book book_id : %d
", book->book_id);
}
讓我們編譯和運(yùn)行上面的程序,這將產(chǎn)生以下結(jié)果:
Book title : C Programming Book author : Nuha Ali Book subject : C Programming Tutorial Book book_id : 6495407 Book title : Telecom Billing Book author : Zara Ali Book subject : Telecom Billing Tutorial Book book_id : 6495700
位字段
位字段允許數(shù)據(jù)在一個(gè)結(jié)構(gòu)體包裝。這是特別有用的,當(dāng)內(nèi)存或存儲(chǔ)數(shù)據(jù)非常寶貴。典型的例子:
包裝幾個(gè)對(duì)象到一個(gè)機(jī)器語(yǔ)言。例如1位標(biāo)志能夠壓縮長(zhǎng)度
讀取外部的文件格式 - 非標(biāo)準(zhǔn)的文件格式可以讀出。例如: 9位整數(shù)。
C語(yǔ)言允許我們通過(guò)結(jié)構(gòu)定義:bit 長(zhǎng)度的變量之后。例如:
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;
在這里,packed_struct包含6個(gè)成員:四個(gè)1位標(biāo)志s f1..f3, 一個(gè) 4 位類型和9位my_int。
C語(yǔ)言自動(dòng)包裝上述位字段盡可能緊湊,條件是字段的最大長(zhǎng)度小于或等于計(jì)算機(jī)的整數(shù)字長(zhǎng)。如果不是這種情況,那么一些編譯器可以允許,而其他將重疊存儲(chǔ)在下一個(gè)字段的存儲(chǔ)器。
指針和數(shù)組:
這是永遠(yuǎn)繞不開(kāi)的話題,首先是引用:
struct stuff *ref = &Huqinwei;
ref->age = 100;
printf("age is:%d\n",Huqinwei.age);
打印可見(jiàn)變化
指針也是一樣的
struct stuff *ptr;
ptr->age = 200;
printf("age is:%d\n",Huqinwei.age);
結(jié)構(gòu)體也不能免俗,必須有數(shù)組:
struct test{
int a[3];
int b;
};
//對(duì)于數(shù)組和變量同時(shí)存在的情況,有如下定義方法:
struct test student[3] = {{{66,77,55},0},
{{44,65,33},0},
{{46,99,77},0}};
//特別的,可以簡(jiǎn)化成:
struct test student[3] = {{66,77,55,0},
{44,65,33,0},
{46,99,77,0}};
變長(zhǎng)結(jié)構(gòu)體:
可以變長(zhǎng)的數(shù)組
#include <stdio.h>
#include <malloc.h>
#include <string.h>
typedef struct changeable{
int iCnt;
char pc[0];
}schangeable;
main(){
printf("size of struct changeable : %d\n",sizeof(schangeable));
schangeable *pchangeable = (schangeable *)malloc(sizeof(schangeable) + 10*sizeof(char));
printf("size of pchangeable : %d\n",sizeof(pchangeable));
schangeable *pchangeable2 = (schangeable *)malloc(sizeof(schangeable) + 20*sizeof(char));
pchangeable2->iCnt = 20;
printf("pchangeable2->iCnt : %d\n",pchangeable2->iCnt);
strncpy(pchangeable2->pc,"hello world",11);
printf("%s\n",pchangeable2->pc);
printf("size of pchangeable2 : %d\n",sizeof(pchangeable2));
}
運(yùn)行結(jié)果
size of struct changeable : 4 size of pchangeable : 4 pchangeable2->iCnt : 20 hello world size of pchangeable2 : 4
結(jié)構(gòu)體本身長(zhǎng)度就是一個(gè)int長(zhǎng)度(這個(gè)int值通常只為了表示后邊的數(shù)組長(zhǎng)度),后邊的數(shù)組長(zhǎng)度不計(jì)算在內(nèi),但是該數(shù)組可以直接使用。
(說(shuō)后邊是個(gè)指針吧?指針也占長(zhǎng)度!這個(gè)是不占的!原理很簡(jiǎn)單,這個(gè)東西完全是數(shù)組后邊的尾巴,malloc開(kāi)辟的是一片連續(xù)空間。其實(shí)這不應(yīng)該算一個(gè)機(jī)制,感覺(jué)應(yīng)該更像一個(gè)技巧吧)
結(jié)構(gòu)體嵌套:
結(jié)構(gòu)體嵌套其實(shí)沒(méi)有太意外的東西,只要遵循一定規(guī)律即可:
//對(duì)于“一錘子買(mǎi)賣”,只對(duì)最終的結(jié)構(gòu)體變量感興趣,其中A、B也可刪,不過(guò)最好帶著
struct A{
struct B{
int c;
}
b;
}
a;
//使用如下方式訪問(wèn):
a.b.c = 10;
特別的,可以一邊定義結(jié)構(gòu)體B,一邊就使用上:
struct A{
struct B{
int c;
}b;
struct B sb;
}a;
使用方法與測(cè)試:
a.b.c = 11;
printf("%d\n",a.b.c);
a.sb.c = 22;
printf("%d\n",a.sb.c);
結(jié)果無(wú)誤。
- C語(yǔ)言中結(jié)構(gòu)體、聯(lián)合體的成員內(nèi)存對(duì)齊情況
- C語(yǔ)言中結(jié)構(gòu)體(struct)的幾種初始化方法
- 淺談C語(yǔ)言中結(jié)構(gòu)體的初始化
- C語(yǔ)言 結(jié)構(gòu)體(Struct)詳解及示例代碼
- 詳解C語(yǔ)言結(jié)構(gòu)體中的函數(shù)指針
- C語(yǔ)言 結(jié)構(gòu)體數(shù)組詳解及示例代碼
- C語(yǔ)言結(jié)構(gòu)體定義的方法匯總
- 深入理解C語(yǔ)言內(nèi)存對(duì)齊
- C語(yǔ)言、C++內(nèi)存對(duì)齊問(wèn)題詳解
- C語(yǔ)言中結(jié)構(gòu)體與內(nèi)存對(duì)齊實(shí)例解析
相關(guān)文章
c++獲取sqlite3數(shù)據(jù)庫(kù)表中所有字段的方法小結(jié)
本文給大家分享c++獲取sqlite3數(shù)據(jù)庫(kù)表中所有字段的三種常用方法,本文針對(duì)每一種方法給大家詳細(xì)介紹,需要的的朋友通過(guò)本文一起學(xué)習(xí)吧2016-11-11
高效實(shí)現(xiàn)整型數(shù)字轉(zhuǎn)字符串int2str的方法
下面小編就為大家?guī)?lái)一篇高效實(shí)現(xiàn)整型數(shù)字轉(zhuǎn)字符串int2str的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03
C語(yǔ)言實(shí)現(xiàn)繪制立體餅圖的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何使用C語(yǔ)言實(shí)現(xiàn)繪制立體餅圖,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
C語(yǔ)言詳細(xì)分析講解內(nèi)存管理malloc realloc free calloc函數(shù)的使用
C語(yǔ)言內(nèi)存管理相關(guān)的函數(shù)主要有realloc、calloc、malloc、free等,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言內(nèi)存管理realloc、calloc、malloc、free函數(shù)的相關(guān)資料,需要的朋友可以參考下2022-05-05

