欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談C語(yǔ)言結(jié)構(gòu)體

 更新時(shí)間:2021年10月20日 15:23:45   作者:Ersansui  
本文主要介紹C語(yǔ)言 結(jié)構(gòu)體的知識(shí),學(xué)習(xí)C語(yǔ)言肯定需要學(xué)習(xí)結(jié)構(gòu)體,這里詳細(xì)說(shuō)明了結(jié)構(gòu)體并附示例代碼,供大家參考學(xué)習(xí),有需要的小伙伴可以參考下

前言

在C語(yǔ)言中,除了內(nèi)置的許多數(shù)據(jù)類型,C語(yǔ)言還為我們提供了自定義的數(shù)據(jù)類型,其中就包括結(jié)構(gòu)體這一數(shù)據(jù)類型。

今天就讓我們來(lái)學(xué)習(xí)一下與結(jié)構(gòu)體相關(guān)的知識(shí)吧!

在這里插入圖片描述

什么是結(jié)構(gòu)體

首先我們要知道,什么是結(jié)構(gòu)體?

在現(xiàn)實(shí)生活中,每一個(gè)事物都是復(fù)雜的,擁有許多的屬性,為了表示這些屬性,我們不可能用單一的數(shù)據(jù)類型來(lái)表示。

例如:一只貓具有的屬性有:年齡、體重、名字、品種等等。

為了描述這只貓的屬性,我們可以用整型變量來(lái)記錄年齡、用浮點(diǎn)型變量來(lái)記錄體重,用字符數(shù)組來(lái)記錄名字和體重等等。

但是,這就需要我們創(chuàng)建多個(gè)變量來(lái)表示這只貓。就以上面的栗子來(lái)說(shuō),如果我們只需要表示一只貓的屬性,就需要?jiǎng)?chuàng)建四次變量,這倒也可以接收,但如果我們要表示100只貓呢?我們就不可能每一只貓都單獨(dú)的創(chuàng)建四次變量了吧?

我們可以知道,每一次貓的屬性基本上都是相同的,無(wú)外乎年齡、體重、名字、品種等等,那么我們可不可把這些屬性抽象出來(lái)呢?答案是肯定的,這就是我們的結(jié)構(gòu)體!

結(jié)構(gòu)體類型的聲明

結(jié)構(gòu)體聲明的格式如下:

struct tag
{
member-list;
}variable-list;

代碼演示如下

struct Stu
{
char name[20];//名字
int age;//年齡
char sex[5];//性別
char id[20];//學(xué)號(hào)
};//分號(hào)不能丟

結(jié)構(gòu)體有時(shí)候還可以進(jìn)行特殊的聲明

例如,不完全聲明

//匿名結(jié)構(gòu)體類型
struct
{
int a;
char b;
float c;
}x;
 struct
{
int a;
char b;
float c;
}a[20], *p;

上面的兩個(gè)結(jié)構(gòu)在聲明的時(shí)候省略掉了結(jié)構(gòu)體標(biāo)簽(tag)。

那么,問(wèn)題來(lái)了?

//在上面代碼的基礎(chǔ)上,下面的代碼合法嗎?
p = &x;

答案是否定的。

編譯器會(huì)把上面的兩個(gè)聲明當(dāng)成完全不同的兩個(gè)類型。

所以是非法的。

結(jié)構(gòu)的自引用

在結(jié)構(gòu)中包含一個(gè)類型為該結(jié)構(gòu)本身的成員是否可以呢?

//代碼1
struct Node
{
int data;
struct Node next;
};
//可行否?

上述代碼是否可行呢?

答案也是否定的,結(jié)構(gòu)體內(nèi)部的成員變量不可包含結(jié)構(gòu)體本身,否則就會(huì)無(wú)限套娃,死循環(huán)下去了。

當(dāng)我們想要結(jié)構(gòu)體里面還能有一個(gè)變量能夠指向一個(gè)結(jié)構(gòu)體的話,我們可以利用指針。

正確的自引用方式如下:

//代碼2
struct Node
{
int data;
struct Node* next;
};

結(jié)構(gòu)體變量的定義和初始化

有了結(jié)構(gòu)體類型,那如何定義變量,其實(shí)很簡(jiǎn)單。

我們可以先聲明結(jié)構(gòu)體類型,然后直接再后面定義結(jié)構(gòu)體。

也可以先聲明結(jié)構(gòu)體類型,然后單獨(dú)的定義結(jié)構(gòu)體。

我們可以再定義結(jié)構(gòu)體的同時(shí)對(duì)其進(jìn)行初始化。

還可以先單獨(dú)定義一個(gè)結(jié)構(gòu)體,然后再單獨(dú)對(duì)其初始化。

具體看下面的代碼演示:

 struct Point
{
int x;
int y;
}p1; //聲明類型的同時(shí)定義變量p1
 
struct Point p2; //定義結(jié)構(gòu)體變量p2
 
//初始化:定義變量的同時(shí)賦初值。
struct Point p3 = {x, y};
 
struct Stu     //類型聲明
{
char name[15];//名字
int age;    //年齡
};
 struct Stu s = {"zhangsan", 20};//初始化
 
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {10, {4,5}, NULL}; //結(jié)構(gòu)體嵌套初始化
 
struct Node n2 = {20, {5, 6}, NULL};//結(jié)構(gòu)體嵌套初始化

結(jié)構(gòu)體的使用

結(jié)構(gòu)體的使用方法有兩種:一是結(jié)構(gòu)體直接使用成員變量,二是利用結(jié)構(gòu)體指針來(lái)引用成員變量。

具體看下面的代碼演示:

struct Stu
{	
	double sco;//分?jǐn)?shù)
	int age;//年齡
	char sex;//性別
};//分號(hào)不能丟
 
int main(){
 	struct Stu s1;
	struct Stu* p;
	p = &s1;
 	//結(jié)構(gòu)體直接訪問(wèn)成員變量
	s1.age = 10;
	s1.sco = 88.8;
	s1.sex = 'N';
 	//通過(guò)結(jié)構(gòu)體指針來(lái)訪問(wèn)
	p->age = 20;
	p->sco = 95.5;
	p->sex = 'W';
 	return 0;
}
 

結(jié)構(gòu)體內(nèi)存對(duì)齊

在我們已經(jīng)掌握了結(jié)構(gòu)體的基本使用之后,我們來(lái)探討一個(gè)更加深入的問(wèn)題。

如何計(jì)算結(jié)構(gòu)體的大???

struct S1
{
char c1;
int i;
char c2;
};
printf("%d\n", sizeof(struct S1));

小伙伴們你們認(rèn)為上述代碼的結(jié)構(gòu)是多少呢?

如果你簡(jiǎn)單的認(rèn)為是:1+4+1 = 6,那么你就錯(cuò)啦!

這段代碼在VS編譯器的默認(rèn)情況下的運(yùn)行結(jié)果為:12

為什么會(huì)這樣呢?

這是因?yàn)?,在?nèi)存中,存在著結(jié)構(gòu)體對(duì)齊!

結(jié)構(gòu)體對(duì)齊規(guī)則如下:

第一個(gè)成員始終在與結(jié)構(gòu)體變量偏移量為0處。其他成員變量要對(duì)齊到對(duì)齊數(shù)的整數(shù)倍的地址處。對(duì)齊數(shù) = 編譯器默認(rèn)的一個(gè)對(duì)齊數(shù) 與 該成員變量本身大小的較小值。結(jié)構(gòu)體總大小為最大對(duì)齊數(shù)(每個(gè)成員變量都有一個(gè)對(duì)齊數(shù))的整數(shù)倍。如果嵌套了結(jié)構(gòu)體的情況,嵌套的結(jié)構(gòu)體對(duì)齊到自己的最大對(duì)齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整體大小就是所有最大對(duì)齊數(shù)(含嵌套結(jié)構(gòu)體的對(duì)齊數(shù))的整數(shù)倍。

提示:VS編譯器默認(rèn)的對(duì)齊數(shù)為8

我們回看上面那段代碼,并畫圖分析。

在這里插入圖片描述

注意

我們可以修改編譯器的默認(rèn)對(duì)齊數(shù),我們只需要加上這樣一句代碼就可以

//這里的數(shù)字就是我們想要修改稱為的大小
//例如這里我們就修改稱為了4
 #pragma pack(4)
 

以上就是結(jié)構(gòu)體對(duì)齊的相關(guān)知識(shí),由于這一部分內(nèi)容比較難,所以小伙伴們一定要多加練習(xí)哦!

結(jié)構(gòu)體傳參

我們先看一段代碼

struct S
{
int data[1000];
int num;
};
struct S s = {{1,2,3,4}, 1000};
 //結(jié)構(gòu)體傳參
void print1(struct S s)
{
printf("%d\n", s.num);
}
 //結(jié)構(gòu)體地址傳參
void print2(struct S* ps)
{
printf("%d\n", ps->num);
}
 int main()
{
print1(s);  //傳結(jié)構(gòu)體
print2(&s); //傳地址
return 0;
}

上面的 print1 和 print2 函數(shù)哪個(gè)好些?

答案顯然是printf2函數(shù)。

原因如下:

函數(shù)傳參的時(shí)候,參數(shù)是需要壓棧,會(huì)有時(shí)間和空間上的系統(tǒng)開(kāi)銷。如果傳遞一個(gè)結(jié)構(gòu)體對(duì)象的時(shí)候,結(jié)構(gòu)體過(guò)大,參數(shù)壓棧的的系統(tǒng)開(kāi)銷比較大,所以會(huì)導(dǎo)致性能的下降。

因此

我們?cè)诮Y(jié)構(gòu)體傳參的時(shí)候,需要傳結(jié)構(gòu)體的地址。

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

最新評(píng)論