1. 程式人生 > 程式設計 >C語言結構體的一些理解

C語言結構體的一些理解

前言

最忙碌的一週已然結束,疲憊之餘想和大家聊一聊對C語言中結構體的認識。水平不足,如有問題請大家指正。

一、對結構體的理解

我們知道C語言中有基本資料型別:

1、整(數)型:

int:基本整型,用於儲存整數,佔4個位元組,預設值為0

short:短整型,佔2個位元組

long:長整型,佔4個位元組

long long:雙長整型,佔8個位元組,比較少用

2、浮點型

float:單精度浮點型,佔4個位元組

double:雙精度浮點型,佔8個位元組

3、字元型

char:字元型,用於儲存單字元,佔1個位元組。

(與Java等語言不同的是,c語言中沒有字串型別,需要使用字元型陣列來存放字串)

// 定義字元型陣列並賦值
 char string[3]; 
 string = ”abc”;

除了這些簡單的、不可拆分的原子資料型別,還存在著複合資料型別(也叫構造型別),如列舉型別、陣列型別、結構體型別、共用體型別,這裡我們要討論的就是其中的結構體型別。

注:我認為,資料型別其實包含了兩個概念,首先是將具有相同屬性的資料處理成一個集合,使屬性得以被限定、區分(如int a=“A”;是錯誤的);其次是在這個集合上定義了一些操作,如int型的加減乘除運算。

二、結構體的定義

1.標準定義的格式說明

struct 結構名 
 { 
  資料型別 變數名; 
  資料型別 變數名; 
  ... 
 } ; 

struct關鍵字用來宣告結構體,花括號內的結構體成員由我們任意發揮(若存在相同的資料型別,也可以簡寫:int a,b,c;)。

這裡的結構名叫做結構體的識別符號,類似於int a中的int,但僅僅是類似,請看下面:

//定義一個名為student的結構體
struct student{  
	char name[8];  
	int age;  
	char sex[2];  
}; 

現在我們只是按照自己的需求,完成了對結構體student的定義,然而這僅僅是個模版,編譯後並沒有為其分配空間,下面讓我們去使用這個新的資料型別:

student stu;//報錯 

在上面提到student這個識別符號只是類似於基本資料型別的型別名稱,因為要想完全在概念上等價,我們需要在前面加上struct關鍵字,即struct student是一個整體,不可以省去struct:

struct student stu; //成功編譯

現在,我們已經成功定義了一個變數stu,系統為其分配了該資料型別(結構體)所需要的儲存空間。
以上兩部分還可以簡寫在一起:

struct student{  
	char name[8];  
	int age;  
	char sex[2];  
}stu;//將stu寫在尾綴,構造結構體的同時完成了對結構體變數的定義,如需多個結構體變數,可以使用逗號分隔開 
struct student{  
	char name[8];  
	int age;  
	char sex[2];  
}stu1,stu2,stu3;//同時定義多個結構體變數,如果需要定義多個具有相同模式的結構體變數時用這種方法比較方便

到這裡,你有沒有想過能不能省略結構體名稱呢?可以。此時定義的結構體稱為匿名結構體(也叫無名結構體):

struct{  
	char name[8];  
	int age;  
	char sex[2];  
}stu1,stu2,stu3;//省略掉識別符號後,依然能完成變數的定義,但此時要注意,我們已經無法通過在結構體外定義新的該結構體的變量了,所以匿名結構體僅僅在確定不會再定義其他結構體變數的時候使用

2.含typedef定義的格式說明

typedef關鍵字,作用是給一種資料型別定義一個新名字。這裡的資料型別包括內部資料型別(int,char等基本資料型別)和自定義的資料型別(struct等)。使用typedef起別名有兩個好處,一是給變數一個易記、含義明確的新名字,二是簡化一些比較複雜的型別宣告(如struct student中的struct)。

typedef struct student{   
	char name[8];   
	int age;   
	char sex[2];   
}xuesheng;
xuesheng stu;//省略struct,使用別名完成變數stu的建立

現在,仔細閱讀的你不難發現:此時尾綴xuesheng的地位已經不可與同日而語了,時過境遷,它不再是我們偷懶定義出來的變數,而是結構體student的別名了,此時struct student與xuesheng等價。

typedef struct{   
	char name[8];   
	int age;   
	char sex[2];   
}xuesheng;//這裡的student依然可以去掉!即使去掉,我們也可以在以後去使用它的別名xuesheng

三.結構體的賦值

一個變數的初始化其實包含兩個內容,一是建立變數,二是為變數賦值以使用。現在讓我們賦值吧。

1、定義結構體之後進行賦值:

a.逐個賦值:

stu.name = "Jack";//錯誤,不能直接給陣列名賦值,因為陣列名是一個常量
strcpy(stu.name,"Chenhao");//不能直接給陣列名賦值,因為陣列名是一個常量。
stu.num = 21;
strcpy(stu.sex,"男");

b.整體賦值:

stu = (struct Student){"Chenhao",21,"男"};//此時需要強制型別轉換,因為陣列賦值也是使用{},不轉換的話系統無法區分!
stu = (xuesheng){"Chenhao","男"};//別忘了也可以用等價的別名喲~

2、定義結構體同時完成賦值:

struct student{   
	char name[8];   
	int age;   
	char sex[2];   
}stu = {"Chenhao","男"};//此時很直觀是在為結構體變數賦值,因此不需要強制型別轉換

3、複製已經初始化的結構體變數以進行賦值:

struct student{   
	char name[8];   
	int age;   
	char sex[2];   
}stu = {"Chenhao","男"};
struct student stu1 = stu;//不是通過指標指向來賦值,確確實實是複製了一份相同的stu成員變數給放到了新變數stu1的儲存空間裡,也就是stu1如實地開闢了自己的空間

以上賦值的方式需要注意初始化值的型別和順序要與結構體宣告時成員對應的型別和順序保持一致!另外,部分初始化的方式請移步自行查閱。

四.結構體的使用

與結構體陣列的成員訪問相同,一樣放在結構體陣列中講。

五.結構體陣列(一維)

結構體型別也與基本資料型別一樣,可以作為陣列的元素的型別。

結構陣列定義格式:

struct 結構名 { 
成員列表 
} 陣列名[陣列長度]; 

如:

struct student{
 char name[8];   
	int age;   
	char sex[2]; 
}stu[145];//定義一個結構結構陣列stu,共有145個元素,即145個學生的學生資訊

結構體陣列的賦值

//整體賦值:
stu = (struct Student){{"Zhangsan",18,"男"},{"Lisi",15,"女"},......}; 
stu[0] = (struct Student){"Chenhao","男"};
//結構體變數成員逐個賦值:
strcpy(stu[144].name,"Smith");
stu[144].age = 10;
stu[144].sex = "女";
//逐個輸出結構陣列的元素
int length = sizeof(stu) / sizeof(struct student);//結構體陣列的長度,結構體陣列變數大小/單個模版大小
for (int i = 0; i<length; i++) { 
 printf("姓名:%s 年齡:%d 性別:%s \n",stu[i].name,stu[i].age,stu[i].sex);
}

結構體陣列小歸納:

名稱 含義
stu student結構體陣列
stu[2] student結構的一個變數,為第三個同學
stu[2].name char型陣列,第三個同學的名字陣列
stu[2].name[0] 第三個同學的名字的首字母

五.結構體與指標

1、指標指向結構體

//直接
struct student{
 char name[8];   
	int age;   
	char sex[2]; 
}*pstu;
//後續間接
typedef struct student{
 char name[8];   
	int age;   
	char sex[2]; 
}stu;
stu *pstu;//定義了一個指標變數,它只能指向Student結構體型別的結構體變數

如果想把已經定義的結構體變數交給一個指標,則必須用取址符&:

struct student{
 char name[8];   
	int age;   
	char sex[2]; 
}stu;
pstu =stu//錯誤
pstu =&stu//正確

(這裡要說明的是,結構體變數名稱單獨拿出來代表變數全體成員值的集合,這與陣列不同,陣列名稱在使用時直接轉化為該陣列的起始地址)

2、通過結構指標間接訪問成員值:

(*結構指標變數). 成員名

結構指標變數 -> 成員名(我們管“->”叫做“箭頭”)

(*pstu).name;
//或
pstu->name;

注意(* pstu).name的小括號不能省略,成員符“.”優先順序最大,取值符“ *”優先順序在其次,去掉括號就相當於 *(pstu.name)了。

總結

格式千千萬,只有全掌握才能閱讀別人的程式碼,但在實際開發中最推薦的格式依然是:

typedef struct student{   
	char name[8];   
	int age;   
	char sex[2];   
}xuesheng;

也不要忘了在整體賦值且在結構體外賦值時的強制轉換。

如果有所收穫,點個讚唄~

最後:

#include<stdio.h>

int main(){
	printf("aiweiye forever.");
}

以上。

到此這篇關於C語言結構體的文章就介紹到這了,更多相關C語言結構體內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!