引言
不管什么樣的編程語言,數(shù)據(jù)類型的不斷衍生都是為了不同場(chǎng)合對(duì)其進(jìn)行不同處理或管理。 比如單一的變量,我們可以定義成char, short,,int,float, double等;而如果需要管理多個(gè)同一類型的數(shù)據(jù)就可以使用數(shù)組來統(tǒng)一管理;那么如果是不同的數(shù)據(jù)類型,但是彼此是相關(guān)聯(lián)的呢? 此時(shí)就可以使用結(jié)構(gòu)體來統(tǒng)一管理,這也是面對(duì)對(duì)象的基本思想。比如一個(gè)學(xué)生,他有如下信息: 名字(char *), 年齡(uint8), 成績(jī)(float)等。今天我們就來說說結(jié)構(gòu)體的基本使用,后續(xù)再深入研究。
結(jié)構(gòu)體的定義
使用struct關(guān)鍵字定義原生結(jié)構(gòu)體類型
struct people{ char name[20]; int age;};
使用typedef類型自定義結(jié)構(gòu)體類型
typedef struct people1{ char name[20]; int age; }people1_t;
兩種方式的有何不同呢? 第一種屬于原生結(jié)構(gòu)體類型,在定義變量之前,都需要加上struct people
struct people p1;
而第二種使用typedef關(guān)鍵字自定義了people_t類型(people1_t等同于struct people1), 即在定義變量時(shí),只需要在變量之前寫上people_t即刻。
people1_t p2;
這兩種方式都可,用戶根據(jù)自己的習(xí)慣選擇其中一種即刻,個(gè)人推薦第二種,定義比較方便~
定義結(jié)構(gòu)體變量和初始化
如上所述,使用第一種struct people定義結(jié)構(gòu)體變量時(shí),有如下方式:
struct people{ char name[20]; int age;};int main(void){ struct people p1; //使用struct people定義變量p1 return 0;}
或:
//定義類型的同時(shí)定義變量struct student{ char name[20]; int age;}std;int main(void){ std.age =23; //直接使用std結(jié)構(gòu)體變量 return 0;}
使用typedef方式定義結(jié)構(gòu)體變量
typedef struct people1{ char name[20]; int age; }people1_t;int main(void){ people1_t p2; return 0;}
接下來我們?cè)俳榻B結(jié)構(gòu)體的兩種方式初始化:
#include 《stdio.h》#include 《string.h》struct people{ char name[20]; int age;};typedef struct people1{ char name[20]; int age; }people1_t;int main(void){ //方式一:在定義的變量的同時(shí)初始化 struct people p1 ={ .name = “xiaoming”, .age = 23 }; people1_t p2; //方式二: 定義變量后,再對(duì)其初始化 strcpy(&p2.name[0], “xiaohong”); p2.age = 45; printf(“p1.name = %s, age = %d. ”, p1.name, p1.age); printf(“p2.name = %s, age = %d. ”, p2.name, p2.age); return 0;}
編譯運(yùn)行:
結(jié)構(gòu)體的元素訪問
在C語言中有兩種方式訪問,分別是“。”和“-》”, 具體參考如下代碼:
#include 《stdio.h》#include 《string.h》#include 《stdlib.h》struct people{ char name[20]; int age;};typedef struct people1{ char name[20]; int age; }people1_t;int main(void){ //定義結(jié)構(gòu)體變量,并初始化 struct people p1 ={ .name = “xiaoming”, .age = 18 }; //定義結(jié)構(gòu)體指針變量 people1_t *p2 = NULL; //申請(qǐng)people1_t結(jié)構(gòu)體大小的堆內(nèi)存空間,并將得到的起始地址賦予p2 p2 = (people1_t *)malloc(sizeof(people1_t)); if(NULL != p2) { //初始化 strcpy(&p2-》name[0], “xiaohong”); p2-》age = 26; } //結(jié)構(gòu)體變量通過‘。’來訪問其元素 printf(“p1.name = %s, age = %d. ”, p1.name, p1.age); //結(jié)構(gòu)體變量通過‘-》’來訪問其元素 printf(“p2.name = %s, age = %d. ”, p2-》name, p2-》age);}
編譯運(yùn)行結(jié)果:
以上兩種方式都是使用下標(biāo)式訪問結(jié)構(gòu)體元素, 那么如何使用指針方式訪問呢?
#include 《stdio.h》#include 《string.h》#include 《stdlib.h》struct my_test{ int a; //4 double b; //8 char c; //1};int main(void){ struct my_test s1; s1.a = 12; s1.b = 3.4; s1.c = ‘a(chǎn)’; int *p1 = (int *)&s1; double *p2 = (double *)((long unsigned int)&s1 + 8); char *p3 = (char *)((long unsigned int)&s1 + 8 + 8); printf(“s1.a = %d. ”, s1.a); printf(“s1.b = %.1f. ”, s1.b); printf(“s1.c = %c. ”, s1.c); printf(“===================== ”); printf(“*p1 = %d. ”, *p1); printf(“*p2 = %.1f. ”, *p2); printf(“*p3 = %c. ”, *p3);}
分析:
int *p1 = (int *)&s1,其中&s1為結(jié)構(gòu)體的起始地址,也是首元素a的地址,因此可以通過類型轉(zhuǎn)化后賦值給p1(int *類型,指向int類型的變量a)
double *p2 = (double *)((long unsigned int)&s1 + 8); 其中因?yàn)?s1是作為結(jié)構(gòu)體地址,本身是帶有數(shù)據(jù)類型的,我們通過(long unsigned int)將其轉(zhuǎn)化成普通的長(zhǎng)整型數(shù)值,然后再加上a(8字節(jié))的長(zhǎng)度,之后的地址就是結(jié)構(gòu)體第二個(gè)元素b的地址了,于是乎將得到的地址轉(zhuǎn)化成double *類型賦值給p2,通過p2來訪問。
char *p3 = (char *)((long unsigned int)&s1 + 8 + 8); 與上步驟分析一致, 首先將&s1轉(zhuǎn)化成普通的普通的長(zhǎng)整型數(shù)值,然后加上元素a 和 元素b的數(shù)據(jù)類型長(zhǎng)度,就得到了元素c的地址,再賦值給p3,通過p3來訪問結(jié)構(gòu)體元素c。
編譯運(yùn)行結(jié)果:
總結(jié)
從數(shù)組到結(jié)構(gòu)體的進(jìn)步之處:數(shù)組有2個(gè)明顯的缺陷:第一個(gè)是定義時(shí)必須明確給出大小,且這個(gè)大小在以后不能再更改(這里不考慮可變數(shù)組);第二個(gè)是數(shù)組要求所有的元素的類型必須一致。
結(jié)構(gòu)體就完美解決了數(shù)組的第二個(gè)缺陷的,可以將結(jié)構(gòu)體理解為一個(gè)其中元素類型可以不相同的數(shù)組。結(jié)構(gòu)體完全可以取代數(shù)組,只是在數(shù)組可用的范圍內(nèi)數(shù)組比結(jié)構(gòu)體更簡(jiǎn)單,使用更方便。
-
C語言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136841 -
代碼
+關(guān)注
關(guān)注
30文章
4788瀏覽量
68616 -
變量
+關(guān)注
關(guān)注
0文章
613瀏覽量
28371
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論