国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

一篇文章讓你搞懂自定義類型-----結(jié)構(gòu)體

這篇具有很好參考價值的文章主要介紹了一篇文章讓你搞懂自定義類型-----結(jié)構(gòu)體。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

一篇文章讓你搞懂自定義類型-----結(jié)構(gòu)體,C/C++,c++,c語言

1 結(jié)構(gòu)體

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

1.1.1 結(jié)構(gòu)的基礎(chǔ)知識

結(jié)構(gòu)是一些值的集合,這些值稱為成員變量。結(jié)構(gòu)的每個成員可以是不同類型的變量

1.1.2 結(jié)構(gòu)的聲明

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

例如描述一個學(xué)生

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

1.1.3 特殊的聲明

在聲明結(jié)構(gòu)的時候,可以不完全的聲明
比如

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

上面的兩個結(jié)構(gòu)在聲明的時候省略掉了結(jié)構(gòu)體標(biāo)簽(tag)
那么問題來了

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

警告:
編譯器會把上面的兩個聲明當(dāng)成完全不同的兩個類型
所以是非法的

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

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

//代碼1
struct Node
{
 int data;
 struct Node next;
};
//可行否?
如果可以,那sizeof(struct Node)是多少?

這里涉及到數(shù)據(jù)結(jié)構(gòu)
所謂數(shù)據(jù)結(jié)構(gòu)描述的就是數(shù)據(jù)在內(nèi)存中的組織結(jié)構(gòu)
這個結(jié)構(gòu)體的自引用是錯誤的
你無法計算出sizeof(struct Node)的大小,類似于套娃,一個next變量里面又包含一個結(jié)構(gòu)體,包含一個data
正確的自引用方式

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

data//數(shù)據(jù)域
//struct Node* next//指針域
結(jié)構(gòu)體指針訪問下一個節(jié)點(diǎn)的地址進(jìn)一步訪問到下一個節(jié)點(diǎn)的數(shù)據(jù)
注意

//代碼3
typedef struct
{
 int data;
 Node* next;
}Node;
//這樣寫代碼,可行否?
//解決方案:
typedef struct Node
{
 int data;
 struct Node* next;
}Node;

當(dāng)你去編譯的時候會報錯
這里不能提前使用Node
原因我們要對一個結(jié)構(gòu)體重命名的時候,結(jié)構(gòu)體必須是完整的
這時我對結(jié)構(gòu)體重命名為Node*就無法知道這個Node星從何處而來

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

有了結(jié)構(gòu)體類型,那如何定義變量

struct Point
{
 int x;
 int y;
}p1; //聲明類型的同時定義變量p1
struct Point p2; //定義結(jié)構(gòu)體變量p2
//初始化:定義變量的同時賦初值。
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)體嵌套初始化
//struct SN
//{
//	char c;
//	int i;
//}sn1 = { 'q', 100 }, sn2 = {.i=200, .c='w'};//全局變量
//
//struct S
//{
//	double d;
//	struct SN sn;
//	int arr[10];
//};
//
//int main()
//{
//	//struct SN sn3, sn4;//局部變量
//	//printf("%c %d\n", sn2.c, sn2.i);
//	struct S s = { 3.14, {'a', 99}, {1,2,3} };
//	printf("%lf %c %d\n", s.d, s.sn.c, s.sn.i);
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", s.arr[i]);
//	}
//	return 0;
//}
//

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

我們已經(jīng)掌握了結(jié)構(gòu)體的基本使用了
現(xiàn)在我們深入討論一個問題:計算結(jié)構(gòu)體的大小
這也是一個特別熱門的考點(diǎn): 結(jié)構(gòu)體內(nèi)存對齊

//練習(xí)1
struct S1
{
 char c1;
 int i;
 char c2;
};
printf("%d\n", sizeof(struct S1));
//練習(xí)2
struct S2
{
 char c1;
 char c2;
 int i;
};
printf("%d\n", sizeof(struct S2));

這里打印的結(jié)構(gòu)是12和8
那導(dǎo)致這個結(jié)果的原因是什么呢?
在解釋這個答案之前我們需要了解以下offsetof這個宏
這個宏可以計算結(jié)構(gòu)體成員相較于結(jié)構(gòu)體起始位置的偏移量
一篇文章讓你搞懂自定義類型-----結(jié)構(gòu)體,C/C++,c++,c語言
對于第一個例子
打印偏移量可以發(fā)現(xiàn),結(jié)構(gòu)體成員不是按照順序在內(nèi)存中連續(xù)存放的,而是有一定的對齊規(guī)則的
結(jié)構(gòu)體內(nèi)存對齊規(guī)則:
1:結(jié)構(gòu)體的第一個成員永遠(yuǎn)放在相較于結(jié)構(gòu)體變量起始位置的偏移量為0的位置
2:從第二個成員開始,往后的每個成員都要對齊到某個對其數(shù)的整數(shù)倍處
對其數(shù):結(jié)構(gòu)體成員自身大小和默認(rèn)對其數(shù)的較小值
VS上默認(rèn)對其數(shù)為8
在gcc環(huán)境上沒有默認(rèn)對其數(shù),對其數(shù)就是結(jié)構(gòu)體成員的自身大小
這里需要重點(diǎn)注意以下對其數(shù)
i的自身大小是4,4和8的默認(rèn)較小值為4,所以i必須要對齊到4的倍數(shù)
偏移量4就是4的倍數(shù),一次往后數(shù)4個字節(jié)
目前我們只占用了9個字節(jié)
為什么打印出來是12個字節(jié)呢?
當(dāng)然了這里有第三個注意的點(diǎn)就是:
結(jié)構(gòu)體的總大小,必須是最大對齊數(shù)的整數(shù)倍
最大對齊數(shù)是所有成員的對齊數(shù)中最大的值
所以結(jié)構(gòu)體成員中的最大對齊數(shù)為4,最小值12才是4的倍數(shù),所以我們打印出來12個字節(jié)
一篇文章讓你搞懂自定義類型-----結(jié)構(gòu)體,C/C++,c++,c語言
根據(jù)上圖我們可以發(fā)現(xiàn),結(jié)構(gòu)體成員第一個變量的起始位置為0,即偏移量從0開始
先找各個結(jié)構(gòu)體成員的偏移量,然后找對齊數(shù),算出總的對齊數(shù)再找結(jié)構(gòu)體成員中最大的對齊數(shù)再和總的對齊數(shù)找出對齊數(shù)的倍數(shù)即可
我們通過下圖引出第四個規(guī)則
一篇文章讓你搞懂自定義類型-----結(jié)構(gòu)體,C/C++,c++,c語言
4. 如果嵌套了結(jié)構(gòu)體的情況,嵌套的結(jié)構(gòu)體對齊到自己的最大對齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整
體大小就是所有最大對齊數(shù)(含嵌套結(jié)構(gòu)體的對齊數(shù))的整數(shù)倍
簡而言之就是說結(jié)構(gòu)體S3中的最大對齊數(shù)為8,所以我們要從偏移量為8的位置處開始向下數(shù)16個字節(jié),因?yàn)槲覀儐为?dú)寫出S3這個結(jié)構(gòu)體依靠前3個規(guī)則就可以計算出大小為16個字節(jié),也可以參考第一個和第二個例子進(jìn)行計算
S4中的最大對齊數(shù)為8,所以總大小為32個字節(jié)
講了這么多,為什么要內(nèi)存對齊呢?
大部分的參考資料都是如是說的:

  1. 平臺原因(移植原因)
    不是所有的硬件平臺都能訪問任意地址上的任意數(shù)據(jù)的;某些硬件平臺只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常
  2. 性能原因
    數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對齊
    原因在于,為了訪問未對齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問;而對齊的內(nèi)存訪問僅需要一次訪問
    總體來說:
    結(jié)構(gòu)體的內(nèi)存對齊是拿空間來換取時間的做法
    那在設(shè)計結(jié)構(gòu)體的時候,我們既要滿足對齊,又要節(jié)省空間
    如何做到:
    讓占用空間小的成員盡量集中在一起
//例如:
struct S1
{
 char c1;
 int i;
 char c2;
};
struct S2
{
 char c1;
 char c2;
 int i;
};

S1和S2類型的成員一模一樣,但是S1和S2所占空間的大小有了一些區(qū)別

1.1.7 修改默認(rèn)對齊數(shù)

之前我們見過了 #pragma 這個預(yù)處理指令,這里我們再次使用,可以改變我們的默認(rèn)對齊數(shù)

#include <stdio.h>
#pragma pack(8)//設(shè)置默認(rèn)對齊數(shù)為8
struct S1
{
 char c1;
 int i;
 char c2;
};
#pragma pack()//取消設(shè)置的默認(rèn)對齊數(shù),還原為默認(rèn)
#pragma pack(1)//設(shè)置默認(rèn)對齊數(shù)為1
struct S2
{
 char c1;
 int i;
 char c2;
};
#pragma pack()//取消設(shè)置的默認(rèn)對齊數(shù),還原為默認(rèn)
int main()
{
    //輸出的結(jié)果是什么?
    printf("%d\n", sizeof(struct S1));
     printf("%d\n", sizeof(struct S2));
    return 0;
}

結(jié)論:
結(jié)構(gòu)在對齊方式不合適的時候,我們可以自己更改默認(rèn)對齊數(shù)

1.1.8 結(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ù)哪個好些?
答案是:首選print2函數(shù)。
原因:
函數(shù)傳參的時候,參數(shù)是需要壓棧,會有時間和空間上的系統(tǒng)開銷
如果傳遞一個結(jié)構(gòu)體對象的時候,結(jié)構(gòu)體過大,參數(shù)壓棧的的系統(tǒng)開銷比較大,所以會導(dǎo)致性能的下降
結(jié)論:結(jié)構(gòu)體傳參的時候,要傳結(jié)構(gòu)體的地址。文章來源地址http://www.zghlxwxcb.cn/news/detail-564311.html

到了這里,關(guān)于一篇文章讓你搞懂自定義類型-----結(jié)構(gòu)體的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 一篇文章帶你搞懂GIT、Github、Gitee

    一篇文章帶你搞懂GIT、Github、Gitee

    本文介紹了GIt,GitHub,Gitee的使用,與IDEA的Git配置,跟著文章來做你很快就能學(xué)會操作Git,利用其進(jìn)行版本控制與代碼托管,學(xué)習(xí)Git的使用、Git常用命令、Git分支,分支是團(tuán)隊協(xié)作的基礎(chǔ),介紹了團(tuán)隊內(nèi),外協(xié)作和Github遠(yuǎn)程倉庫的操作、使用IDEA中的Git、IDEA中GIt的使用、在I

    2023年04月19日
    瀏覽(26)
  • 一篇文章帶你搞懂微信小程序的開發(fā)過程

    一篇文章帶你搞懂微信小程序的開發(fā)過程

    小程序想必大家應(yīng)該都不陌生了吧,今天小編帶大家一起來學(xué)習(xí)下微信小程序的開發(fā)過程吧。 這個不一一介紹,網(wǎng)上有教程,申請成功后打開后臺,我們找到小程序,下載微信開發(fā)者工具,如圖: 這里我們選擇普通小程序開發(fā)工具,點(diǎn)擊微信開發(fā)者工具,如圖: 然后選擇相

    2024年02月09日
    瀏覽(26)
  • 一篇文章帶你搞懂動態(tài)規(guī)劃(由暴力遞歸到動態(tài)規(guī)劃)

    一篇文章帶你搞懂動態(tài)規(guī)劃(由暴力遞歸到動態(tài)規(guī)劃)

    ”動態(tài)規(guī)劃“ 的過程相當(dāng)于 記憶化搜索 , 即在普通 遞歸 的過程中用二維數(shù)組進(jìn)行記憶化存儲一些狀態(tài)結(jié)果, 從而避免重復(fù)的計算(剪枝)。 舉一個簡單的例子:在 遞歸法 求解 斐波那契 數(shù)列的過程中, 就進(jìn)行了多次的 重復(fù)計算 , 而動態(tài)規(guī)劃相當(dāng)于是對已經(jīng)計算的狀態(tài)

    2024年02月20日
    瀏覽(24)
  • 顛覆世界的“數(shù)字孿生”到底是什么?這篇文章帶你搞懂全部內(nèi)涵!

    顛覆世界的“數(shù)字孿生”到底是什么?這篇文章帶你搞懂全部內(nèi)涵!

    在春節(jié)很火的電影《流浪地球2》中,已經(jīng)去世的小女孩圖丫丫,被她的父親重新將其個人的信息模型導(dǎo)入最強(qiáng)大的計算機(jī)而“復(fù)活”了。屏幕中的丫丫就是一個數(shù)字孿生體。我們可以看到她的一顰一笑,聽到她跟你的對話,看到她做出反應(yīng)。這就是數(shù)字孿生的另一特色,數(shù)字

    2024年02月01日
    瀏覽(43)
  • 一篇文章帶你搞懂spring6的概念、spring入門與容器IoC詳解(尚硅谷筆記)

    一篇文章帶你搞懂spring6的概念、spring入門與容器IoC詳解(尚硅谷筆記)

    Spring 是一款主流的 Java EE 輕量級開源框架 ,Spring 由“Spring 之父”Rod Johnson 提出并創(chuàng)立,其目的是用于簡化 Java 企業(yè)級應(yīng)用的開發(fā)難度和開發(fā)周期。Spring的用途不僅限于服務(wù)器端的開發(fā)。從簡單性、可測試性和松耦合的角度而言,任何Java應(yīng)用都可以從Spring中受益。Spring 框架

    2023年04月16日
    瀏覽(24)
  • 【運(yùn)維知識高級篇】一篇文章帶你搞懂Git!(Git安裝+全局配置+Git初始化代碼倉庫+Git四大區(qū)域+Git四種狀態(tài)+Git常用命令+Git分支+Git測試代碼回滾)

    版本流程控制系統(tǒng)(version control system)是一種記錄一個或若干個文件內(nèi)容變化,以便將來查閱特定版本內(nèi)容情況的系統(tǒng),它會記錄文件的所有歷史變化,我們可以隨時恢復(fù)到任何一個歷史狀態(tài),同時支持多人協(xié)作開發(fā)。 目錄 常見的版本管理工具 Git安裝與全局配置 Git初始化

    2024年02月02日
    瀏覽(140)
  • 一篇文章搞懂Docker、DockerCompose

    一篇文章搞懂Docker、DockerCompose

    大型項目組件較多,運(yùn)行環(huán)境也較為復(fù)雜,部署時會碰到一些問題: 依賴關(guān)系復(fù)雜,容易出現(xiàn)兼容性問題 開發(fā)、測試、生產(chǎn)環(huán)境有差異 例如一個項目中,部署時需要依賴于node.js、Redis、RabbitMQ、MySQL等,這些服務(wù)部署時所需要的函數(shù)庫、依賴項各不相同,甚至?xí)袥_突。給部

    2024年01月18日
    瀏覽(25)
  • 一篇文章搞懂華為的ACL

    一篇文章搞懂華為的ACL

    隨著網(wǎng)絡(luò)的飛速發(fā)展,網(wǎng)絡(luò)安全問題日益突出。訪問控制列表 (ACL, Access Control List) 可以通過對網(wǎng)絡(luò)中報文流的精確識別,與其他技術(shù)結(jié)合,達(dá)到控制網(wǎng)絡(luò)訪問行為、防止網(wǎng)絡(luò)攻擊和提高網(wǎng)絡(luò)帶寬利用率的目的,從而切實(shí)保障網(wǎng)絡(luò)環(huán)境的安全性和網(wǎng)絡(luò)服務(wù)質(zhì)量的可靠性。 訪問

    2024年02月06日
    瀏覽(20)
  • 一篇文章搞懂Git與Github

    一篇文章搞懂Git與Github

    Git 是一個開源的 分布式版本控制系統(tǒng) ,Github 是 全球最大的同性交友網(wǎng)站 基于 Git 的 代碼托管平臺 ,因?yàn)橹恢С?Git 作為 唯一的版本庫 格式進(jìn)行托管,故名 GitHub,就是一個平臺上面有無數(shù)個 Git 倉庫——Git 版的百度云,承擔(dān)存儲遠(yuǎn)程倉庫的作用。 唯一版本庫是什么意思?

    2024年02月06日
    瀏覽(24)
  • 搞懂TVS管,有這篇文章就夠了

    摘要:本文主要介紹TVS的工作原理、關(guān)鍵參數(shù)和選型。 TVS(Transient Voltage Suppressors,瞬態(tài)電壓抑制器)又稱雪崩擊穿二極管,是一種高效電路保護(hù)器件,主要是保護(hù)電路不受瞬態(tài)高壓尖峰脈沖(靜電或雷擊浪涌)的沖擊。 TVS是采用半導(dǎo)體工藝制成的單個PN結(jié)或多個PN結(jié)集成的器件,

    2023年04月08日
    瀏覽(30)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包