欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:C語言?定義類型:結構體

柚子快報激活碼778899分享:C語言?定義類型:結構體

http://yzkb.51969.com/

目錄

前言

1. 結構體類型的聲明

1.1 結構的聲明

1.2 結構體變量的創(chuàng)建和初始化

1.3?結構的特殊聲明

1.4?結構的?引?

2.結構體內存對齊

2.1 對?規(guī)則

實例講解

2.2 為什么存在內存對??

2.3 修改默認對?數

3. 結構體傳參

4.?結構體實現位段

4.1 什么是位段

?4.2 位段的內存分配

4.3 位段的跨平臺問題

4.4 位段的應?

4.5 位段使?的注意事項

結語

?編輯

前言

在C語言中提供了許多內置類型,例如:int、short、long、longlong、char、float、double等,但是如果想描述一個學生時,這些單一的內置類型是無法做到的,描述一個學生需要包含名字、年齡、身高、體重等特征,為了解決這類問題,C語言中引入了結構體的概念,結構體這種自定義的數據類型,能讓我們自己創(chuàng)建出合適的類型,那么接下來學習一下結構體該如何使用吧?。?!

1. 結構體類型的聲明

1.1 結構的聲明

定義結構體的基本形式:

struct tag? ?//結構體名稱

{

member-list;? //結構體成員列表

}variable-list;? ?//結構體變量列表

例如描述一個學生的基本信息:

struct stu

{

char name[20]; //學生姓名

int age; //學生年齡

int stu_id[10];//學生學號

char sex[5]; //學生性別

}

1.2 結構體變量的創(chuàng)建和初始化

既然已經學習了結構體是如何聲明的,那么來看看結構體變量是如何創(chuàng)建和初始化的:

1.按照結構體成員順序進行初始化、

?

#include

struct Stu

{

char name[20]; //學生姓名

int age; //學生年齡

char stu_id[20];//學生學號

char sex[5]; //學生性別

};

int main()

{

//按照結構體成員的順序初始化

struct Stu s = { "張三", 20, "男", "20230818001" };//s就是結構體變量

printf("name: %s\n", s.name);

printf("age : %d\n", s.age);

printf("sex : %s\n", s.sex);

printf("stu_id : %s\n", s.stu_id);

return 0;

}

?

2.按照指定的順序初始化

#include

struct Stu

{

char name[20]; //學生姓名

int age; //學生年齡

char stu_id[20];//學生學號

char sex[5]; //學生性別

};

int main()

{

struct Stu s2 = { .age = 18, .name = "lisi", .sex ="女" ,.stu_id = "20230818002"};

printf("name: %s\n", s2.name);

printf("age : %d\n", s2.age);

printf("sex : %s\n", s2.sex);

printf("stu_id : %s\n", s2.stu_id);

}

1.3?結構的特殊聲明

在聲明結構的時候,可以不完全的聲明,例如:

struct

{

int a;

char b;

float c;

}x;

struct

{

int a;

char b;

float c;

}* p;

int main()

{

p = &x;

return 0;

}

上?的兩個結構在聲明的時候省略掉了結構體標簽(tag),此時是匿名結構體類型,那么此時主函數中的p=&x 這個代碼是合法的嗎?

注意:編譯器會把上?的兩個聲明(兩個匿名結構體類型)當成完全不同的兩個類型,所以是?法的。 匿名的結構體類型,如果沒有對結構體類型重命名的話,基本上只能使??次。

1.4?結構的?引?

結構體自引用指的是在結構體定義中,結構體本身作為該結構體類型中的一個成員出現,但是直接進行結構體自引用會引發(fā)無限遞歸的結構體定義,就是結構體試圖包含自己,導致編譯器無法確定結構體的大小。

例如:

struct Node

{

int data;

struct Node next;

};

?個結構體中再包含?個同類型的結構體變量,這樣結構體變量的? ?就會?窮的?,是不合理的,那么正確的自引用方式是怎么樣的呢?

struct Node

{

int data;

struct Node* next;

};

?使用指向自己類型的指針來實現自引用的效果,這種方式不會引發(fā)無限遞歸的問題,并且指針的大小是固定(4/8字節(jié))。

2.結構體內存對齊

我們已經掌握了結構體的基本使?了。 現在我們深?討論?個問題:計算結構體的??,要計算結構體大小,我們就要明白結構體成員在內存中是如何進行存儲的,這就涉及到結構體內存對齊的問題。

2.1 對?規(guī)則

1. 結構體的第?個成員對?到和結構體變量起始位置偏移量為0的地址處。

2. 其他成員變量要對?到某個數字(對?數)的整數倍的地址處。 對?數 = 編譯器默認的?個對?數 與 該成員變量??的較?值。?VS 中默認的值為 8 - Linux中 gcc 沒有默認對?數,對?數就是成員??的??。

3. 結構體總??為最?對?數(結構體中每個成員變量都有?個對?數,所有對?數中最?的)的 整數倍。

4. 如果嵌套了結構體的情況,嵌套的結構體成員對?到??的成員中最?對?數的整數倍處,結構體的整體??就是所有最?對?數(含嵌套結構體中成員的對?數)的整數倍。

什么意思呢?我們接下來根據實例進行探索(vs2022環(huán)境)

實例講解

練習1:

struct S1

{

char c1;

int i;

char c2;

};

struct S2

{

char c1;

char c2;

int i;

};

int main()

{

printf("%d\n", sizeof(struct S1));

printf("%d\n", sizeof(struct S2));

return 0;

}

S1與S2的區(qū)別就在結構體成員的位置的不同,那么里面的成員都是一樣的,為什么S1和S2的大小是不一樣的呢?這就涉及到結構體內存對齊的規(guī)則了。

畫圖演示:

所以此時S1的大小為12個字節(jié),S2的大小也是通過對齊規(guī)則進行判斷的,這里就不在進行演示啦。

練習2:(結構體嵌套問題)

struct S3

{

double d;

char c;

int i;

};

//結構體嵌套問題

struct S4

{

char c1;

struct S3 s3;

double d;

};

int main()

{

printf("%d\n", sizeof(struct S3));

printf("%d\n", sizeof(struct S4));

return 0;

}

接下來我們來計算一下S3和S4的大小,根據之前講過的對齊規(guī)則,我們可以快速的計算出S3的大小是16個字節(jié),那么我們重點來講一下S4的大小該如何計算。

畫圖演示:

運行結果:

2.2 為什么存在內存對??

1. 平臺原因 (移植原因)

不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特定 類型的數據,否則拋出硬件異常。

2. 性能原因

數據結構(尤其是棧)應該盡可能地在?然邊界上對?。原因在于,為了訪問未對?的內存,處理器需要 作兩次內存訪問;?對?的內存訪問僅需要?次訪問。假設?個處理器總是從內存中取8個字節(jié),則地 址必須是8的倍數。如果我們能保證將所有的double類型的數據的地址都對?成8的倍數,那么就可以 ??個內存操作來讀或者寫值了。否則,我們可能需要執(zhí)?兩次內存訪問,因為對象可能被分放在兩 個8字節(jié)內存塊中。

總體來說:結構體的內存對?是拿空間來換取時間的做法。

那么在設計結構體的時候,我們該如何盡可能的讓占用空間更小呢?

解決辦法:讓占?空間?的成員盡量集中在?起,就比如練習一中的例子,S1 和 S2 類型的成員?模?樣,但是 S1 和 S2 所占空間的??有了?些區(qū)別。

2.3 修改默認對?數

結構體在對??式不合適的時候,我們可以??更改默認對?數。

#pragma 這個預處理指令,可以改變編譯器的默認對?數。

#include

#pragma pack(1)//設置默認對?數為1

struct S

{

char c1;

int i;

char c2;

};

#pragma pack()//取消設置的對?數,還原為默認

int main()

{

printf("%d\n", sizeof(struct S));

return 0;

}

運行結果:

這里將默認對齊數從8變成了1,再根據對齊規(guī)則,得到的大小就是6個字節(jié)。

3. 結構體傳參

struct S

{

int data[1000];

int num;

};

struct S s = {{1,2,3,4}, 1000};

//結構體傳參

void print1(struct S s)

{

printf("%d\n", s.num);

}

//結構體地址傳參

void print2(struct S* ps)

{

printf("%d\n", ps->num);

}

int main()

{

print1(s); //傳結構體

print2(&s); //傳地址

return 0;

}

結構體傳參有兩種方式:一種是值傳遞另一種是址傳遞

值傳遞的方式:調用函數的時候,系統(tǒng)要為函數的形參部分分配空間來存放實參的值,相當于又開辟了一份相同的空間。

址傳遞的方式:調用函數的時候,函數的形參部分用結構體指針接收實參的地址,指向的就是實參,系統(tǒng)不會再為形參部分開辟一份與實參相同的空間,可以節(jié)約對內存空間的占用。

那么print1(值傳遞)和 printf2(址傳遞)哪種方式更好呢?其實 printf2 址傳遞的方式更好

原因:

函數傳參的時候,參數是需要壓棧,會有時間和空間上的系統(tǒng)開銷。 如果傳遞?個結構體對象的時候,結構體過?,參數壓棧的的系統(tǒng)開銷?較?,所以會導致性能的下降。

結論: 結構體傳參的時候,盡量傳結構體的地址。

4.?結構體實現位段

4.1 什么是位段

位段的聲明和結構是類似的,有兩個不同:

1. 位段的成員必須是 int、unsigned int 或signed int ,在C99中位段成員的類型也可以選擇其他類型。

2. 位段的成員名后邊有?個冒號和?個數字。(表示成員在內存中所占的比特位)

例如:

struct A

{

int _a:2;

int _b:5;

int _c:10;

int _d:30;

};

?4.2 位段的內存分配

1. 位段的成員可以是 int unsigned int signed int 或者是 char 等類型

2. 位段的空間上是按照需要以4個字節(jié)( int )或者1個字節(jié)( char )的?式來開辟的。

3. 位段涉及很多不確定因素,位段是不跨平臺的,注重可移植的程序應該避免使?位段。

?位段成員在內存中的分配方式(從左到右,從右到左)是由編譯器決定的

//?個例?

struct S

{

char a:3;

char b:4;

char c:5;

char d:4;

};

struct S s = {0};

s.a = 10;

s.b = 12;

s.c = 3;

s.d = 4;

//空間是如何開辟的?

畫圖演示:

4.3 位段的跨平臺問題

1. int 位段被當成有符號數還是?符號數是不確定的。

2. 位段中最?位的數?不能確定。(16位機器最?16,32位機器最?32,寫成27,在16位機器會 出問題。

3. 位段中的成員在內存中從左向右分配,還是從右向左分配,標準尚未定義。

4. 當?個結構包含兩個位段,第?個位段成員?較?,?法容納于第?個位段剩余的位時,是舍棄 剩余的位還是利?,這是不確定的。

總結: 跟結構相?,位段可以達到同樣的效果,并且可以很好的節(jié)省空間,但是有跨平臺的問題存在。

4.4 位段的應?

下圖是?絡協(xié)議中,IP數據報的格式,我們可以看到其中很多的屬性只需要?個bit位就能描述,這? 使?位段,能夠實現想要的效果,也節(jié)省了空間,這樣?絡傳輸的數據報??也會較??些,對?絡 的暢通是有幫助的。

4.5 位段使?的注意事項

位段的?個成員共有同?個字節(jié),這樣有些成員的起始位置并不是某個字節(jié)的起始位置,那么這些位 置處是沒有地址的。內存中每個字節(jié)分配?個地址,?個字節(jié)內部的bit位是沒有地址的。 所以不能對位段的成員使?&操作符,這樣就不能使?scanf直接給位段的成員輸?值,只能是先輸? 放在?個變量中,然后賦值給位段的成員。

例如:

struct A

{

int _a : 2;

int _b : 5;

int _c : 10;

int _d : 30;

};

int main()

{

struct A sa = {0};

scanf("%d", &sa._b);//這是錯誤的

//正確的?范

int b = 0;

scanf("%d", &b);

sa._b = b;

return 0;

}

結語

以上就是自定義類型—結構體的內容啦,希望大家看完后能夠靈活運用結構體,并且明白結構體數據在內存中是如何存儲的,在此感謝大家的觀看?。?!

柚子快報激活碼778899分享:C語言?定義類型:結構體

http://yzkb.51969.com/

推薦文章

評論可見,查看隱藏內容

本文內容根據網絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉載請注明,如有侵權,聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/19534299.html

發(fā)布評論

您暫未設置收款碼

請在主題配置——文章設置里上傳

掃描二維碼手機訪問

文章目錄