摘要:如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數含嵌套結構體的對齊數的整數倍。
?
?
?
?
?
?
結構體的基礎知識: 結構是一些值的集合,這些值稱為成員變量。結構的每個成員可以是不同類型的變量
?
程序一:
#include //聲明一個結構體類型//聲明一個學生類型,是 想通過 學生類型 來創建 學生變量(對象)// 描述學生 : 屬性 + 名字 + 性別 + 年齡 + 電話 struct student// struct 結構體 關鍵字 student 結構體 標簽{ char name[10]; char sex[20]; int age; char telephone[12];// 這四個變量 就是結構體的成員變量}s4,s5,s6; // 創建 結構體 全局變量// 以上所有 就是一個 結構體類型struct student s3; // 創建 結構體 全局變量int main(){ //創建 結構體變量 的方式 struct student s1; struct student s2; // 因為 這兩個變量放在 main 函數里,所以是 局部變量 return 0;}
?
程序一:
#include struct // 缺少一個標簽(名字) 這種結構體類型 稱為 匿名結構體類型 { // 那么問題來了,沒有名字 該 如何 創建 結構體 變量 ? char name[10]; char sex[20]; int age; char telephone[12];}x;// 只有一種方式在結構體末尾分號(;)前面 創建 結構體 全局變量struct // 缺少一個標簽(名字) 這種結構體類型 稱為 匿名結構體類型 { char name[10]; char sex[20]; int age; char telephone[12];}* px;// 在 匿名結構體 的 全部變量 px 前面加上 * ,該 匿名結構體類型 變成了 匿名結構體指針類型// 即 * px 是一個結構體指針int main(){ px = &x; // 經過 編譯器 編譯, 程序報警,該表達式 是 不合法的 //因為 編譯器, 會把 它們 當做 2 種 不同類型 來處理 // 所以 兩種 不同類型 的數據,是無法進行賦值 return 0;}
?
程序一:
#include struct node{ int data; struct node* next;// 如果 沒有 * 號,也就是數 next 是本身的結構體變量,會導致這個結構體所占內存無限大。 // 這里存地址, 存的是下一個數據的地址: //結構體自引用 就是 結構體 用指針 找到 與自身同類型的 結構體變量 // 而不是說 結構體自己 包含 結構體自己 的 變量 : struct node next (error)};int main(){ return 0;}
?
程序二:
#include typedef struct node // 這里的 node 是不能省略的, 要不然 下面 沒有這 struct node* next 類型,只能寫成 node* next{ // 但是 node 是 [把 省略了 node 從而 變成 匿名結構體 的 重命名]。 是后有的, // 也就是說 node 還沒有生成, 就在結構體 調用它, // 這種寫法 是錯誤的 int data; struct node* next;}node; // node : typedef 把 結構體 struct node 簡化成 nodeint main(){ node n; return 0;}
?
?
程序一:
#include struct s{ char c; int a; double d; char arr[20];};int main(){ struct s s = { "c", 100, 3.14, "hellworld" }; printf("%c %d %lf %s/n", s.c, s.a, s.d, s.arr); return 0;}
?
程序二:
#include struct t{ double weight; short age;};struct s{ char c; int a; double d; char arr[20]; struct t st;};int main(){ struct s s = { "c", 100, 3.14, "hellworld", {55.6,30} }; printf("%c %d %lf %s %lf %d/n", s.c, s.a, s.d, s.arr, s.st.weight, s.st.age); return 0;}
?
對齊數 = 編譯器默認 的 一個對齊數 與 成員大小的 較小值
vs 中 默認的值為 8; gcc 沒有默認對齊數(成員的大小,就是對齊數)
比如 結構體里 有一個 成員(變量) 為 整形 int 類型 為 4byte
// 而 vs 中 默認值為 8, 4 < 8, 取 4,
// 那么 該成員的 對齊數 為 4
struct s{ char c1;// 第一個成員 在與 結構體變量 偏移量為 0 的 地址處 (內存所占 1 字節) int a; // a 對齊數 是 4 ,因為 其他成員 變量 要對齊 對齊數(4) 的 整數倍 的 地址處(地址4) // 從 c1(0 地址) 后面開始(從地址 4 開始) 地址 4 處 存放 a,就是說 c1 與 a 之間 隔了 3 個 地址(1,2,3) -> 3 字節 // 此時 a 末尾地址 為 地址8 (因為 a 的存儲 需要 4 byte 空間) char c2;// c2 對齊數 1 ; 其他成員 變量 要對齊 對齊數(1)的 整數倍(倍數為 1) 的 地址處 也就是緊跟 a 后面的 地址8,(char 1 byte)存完之后,末尾地址指向 9; // 無論是地址幾,都是 對齊數 1 的倍數 // 至此,1+3+4+1 為 9 字節 // 結構體 總大小 為9 字節,但此時地址,不是 成員中 最大 對齊數(4) 的整數倍, // 12 滿足 // 所以 結構體的大小 最后 為 12 byte};struct s2{ char c1;// 第一個成員 在與 結構體變量 偏移量為 0 的 地址處 (1字節) char c2;// 對齊數為 1 -> 其他成員 變量 要對齊 對齊數的 整數倍( 倍數為 1 ) 的 地址處(地址1) ,c2 的存儲地址 緊跟在 c1 的后面(2 字節) int a;// 對齊數 4 -> 其他成員 變量 要對齊 對齊數的 整數倍( 倍數為 4 ) 的 地址處(地址4),(c1 是 0 地址,c2 是1 地址,浪費 2,3地址) // 即 來到 地址4, 也就是 a 的地址,也就是說 a 與 c2 隔了 2 個地址(浪費了2字節空間),a 的 存儲 也要 占 4 字節 // 1 + 1 + 2 + 4 == 8 字節 // 成員中 最大對齊數(4) 的整數倍 // 因為 8 == 2*4 > 6 滿足條件 // 所以最后 結構體總大小 為 8};int main(){ struct s s = { 0 }; struct s2 s2 = { 0 }; printf("%d/n", sizeof(s));// 12 printf("%d/n", sizeof(s2));// 8 return 0;}
12 byte ,滿足成員中 最大 對齊數(4) 的整數倍, 即 結構體大小 為 12 byte
?
?
?
?
程序二:
#include struct s3{ double d;// 第一個成員 在 與 結構體 偏移量為 0 的地址處(double 8字節,此時地址 指向地址7) char c;// 對齊數 1 地址8(9字節) int i;// 對齊數 4 c 后面的 是 地址9,不滿足倍數條件,地址 12 滿足(浪費 9,10,11地址,即 3字節空間),即 i 的地址 是 地址12 // i 占 4 字節, // 8 + 1 + 3 +4 == 16 // 16 滿足成員中 最大對齊數(8)的整數倍};int main(){ printf("%d/n", sizeof(struct s3));// 16}
?
?
程序二:
#include struct s3{ double d;// 對齊數 8 地址 7 char c;// 對齊數 1 地址 8 int i;// 對齊數 4 地址 12 i 存儲 需要 4byte ,地址 16 // 結構體大小 16 byte 滿足 最大 對齊數(8) 的整數倍 // 故結構體 真正大小 為 16字節};struct s4{ char c1; // 地址0, 對齊數 1 // 嵌套了結構體的情況,嵌套的結構體 對齊 到自己的 最大 對齊數(8) 的整數倍處 struct s3 s3; // 對齊地址 8 然后 結構體 s3 內存大小 為 16 byte // 存完16byte之后,地址 24 double d; // 對齊數 8 ,地址24 滿足 對齊數 整數倍 地址 // 地址 24 到 地址 32 // 32 滿足 最大 對齊數(8)的整數倍 // 結構體 變量 s4 內存大小 32 字節 };int main(){ printf("%d/n", sizeof(struct s4));// 32}
?
?
?
?
?
?
struct s{ char c1;// 第一個成員 在與 結構體變量 偏移量為 0 的 地址處 (內存所占 1 字節) int a; // a 對齊數 是 4 ,因為 其他成員 變量 要對齊 對齊數(4) 的 整數倍 的 地址處(地址4) // 從 c1(0 地址) 后面開始(從地址 4 開始) 地址 4 處 存放 a,就是說 c1 與 a 之間 隔了 3 個 地址(1,2,3) -> 3 字節 // 此時 a 末尾地址 為 地址8 (因為 a 的存儲 需要 4 byte 空間) char c2;// c2 對齊數 1 ; 其他成員 變量 要對齊 對齊數(1)的 整數倍(倍數為 1) 的 地址處 也就是緊跟 a 后面的 地址8,(char 1 byte)存完之后,末尾地址指向 9; // 無論是地址幾,都是 對齊數 1 的倍數 // 至此,1+3+4+1 為 9 字節 // 結構體 總大小 為9 字節,但此時地址,不是 成員中 最大 對齊數(4) 的整數倍, // 12 滿足 // 所以 結構體的大小 最后 為 12 byte};struct s2{ char c1;// 第一個成員 在與 結構體變量 偏移量為 0 的 地址處 (1字節) char c2;// 對齊數為 1 -> 其他成員 變量 要對齊 對齊數的 整數倍( 倍數為 1 ) 的 地址處(地址1) ,c2 的存儲地址 緊跟在 c1 的后面(2 字節) int a;// 對齊數 4 -> 其他成員 變量 要對齊 對齊數的 整數倍( 倍數為 4 ) 的 地址處(地址4),(c1 是 0 地址,c2 是1 地址,浪費 2,3地址) // 即 來到 地址4, 也就是 a 的地址,也就是說 a 與 c2 隔了 2 個地址(浪費了2字節空間),a 的 存儲 也要 占 4 字節 // 1 + 1 + 2 + 4 == 8 字節 // 成員中 最大對齊數(4) 的整數倍 // 因為 8 == 2*4 > 6 滿足條件 // 所以最后 結構體總大小 為 8};
?
?
程序一:
#include #pragma pack(4) // 設計 默認對齊數 為 4struct s{ char c1;// 1 // 浪費 3 個字節(原本要浪費 7 個 字節,現在只需 3 個字節) double d; // 8 byte 對齊 為 對齊數 4,【4與8 選擇較小的】 的整數倍 的地址 // 存儲 d 需要 8 個字節 加上前面浪費 3 個 和 c1 1個 字節 // 1+3+8 == 12 字節 // 這樣寫法,幫我們 避免 了 4 字節 的 空間浪費};#pragma pack() // 取消設置的 默認 對齊數
?
程序二:
那 我們把 默認對齊數 設置為 1 呢?#include #pragma pack(1) // 設計 默認對齊數 為 1struct s{ char c1;// 1 // 一個字節的都不會浪費 double d; // 8 byte 對齊 為(對齊數 1,【1與8 選擇較小的】) 的整數倍 的地址 // 存儲 d 需要 8 個字節 // 1+8 == 9 字節 (9 是 最大 對齊數(1)的 整數倍) // 這樣寫法,幫我們 避免 了 7 字節 的 空間浪費};#pragma pack() // 取消設置的 默認 對齊數// #pragma pack() 一般設置 默認 對齊數 為 2,4,8, 16 (2的次方數)
?
#include #include struct s{ char c; int i; double d;};int main(){ // offsetof 其實是一個宏,用來表示 成員 相對于 結構體 的 偏移量 printf("%d/n", offsetof(struct s, c));// 0 printf("%d/n", offsetof(struct s, i));// 4 printf("%d/n", offsetof(struct s, d));// 8 return 0; //而且 offsetof 的 參數 傳的是 一個類型,更加說了 offsetof 是一個宏 }
?
?
#include struct s{ int a; char c; double d;};void init(struct s *tmp){ tmp->a = 100; tmp->c = "w"; tmp->d = 3.14;}void print(struct s tmp)// 傳值:如果傳遞的結構體對象的時候,結構體過大(空間過大),容易導致 參數壓棧 的 系統 開銷比較大,從而導致系統性能下降。{ printf("%d %c %lf/n", tmp.a, tmp.c, tmp.d);}void print2(const struct s* tmp) // 傳址 : 最好使用這種方法(節省空間),一個地址在操作系統不改變的情況,永遠都是4個字節大小,{ // const 是為了防止 意外改變 結構體變量地址 指向的 值 printf("%d %c %lf/n", tmp->a, tmp->c, tmp->d);}int main() { struct s s = { 0 }; init(&s); print(s); print2(&s); return 0;}
?
?
?
?
?
程序一:
#include struct a // 按照以下寫法寫結構體成員, a 已經不是個結構體類型了,而是 一個 位段 類型了// 位段 看見成員 都是 int 類型 ,所以,它 一開始 就創建了 4 byte的 空間{ int a : 2;// 2 這里的意思是: a只需要 2 個比特位(bit) int b : 5;// 5 這里的意思是: b只需要 5 個比特位(bit) int c : 10;// 10 這里的意思是: c只需要 10 個比特位(bit) int d : 30;// 30 這里的意思是: d只需要 30 個比特位(bit)};// 一共 47 個 bit 位,由已經創建的 4byte 空間來分配空間, 很明顯 空間不夠 大,只能存入 a,b,c,4 byte 空間 還剩 15 bit d 放不下,怎么辦呢? 在vs 環境中 系統 會舍棄(浪費)剩余的 15 bit 空間 然后, 它再向 空間申請 4 byte(32bit) 空間, 存儲 d 需要 30 bt 空間,這 30 bit 的數據 就存入 這個向系統第二次申請 4 byte 的空間里 至此,數據全部存完,剩余的空間就浪費掉了,也就是說 這 位段 的 內存大小為 8 byteint main(){ struct a a; printf("%d/n", sizeof(a));// 8 byte return 0;}
&ensp;
?
?
程序一:
#include // vs 環境struct s // 因為下面 成員類型 為 char 類型,所以它 一開始 就準備 了 1 byte 空間{ char a : 3;// a 要個 3 bit 位, 由提前準備 1 byte 空間 來分配,還剩 5 bit // char b : 4;// b 要 4 bit 位,由提前準備 1 byte 空間 來分配,還剩 1 bit 空間 char c : 5;// c 要 5 bit 位,由提前準備 1 byte 空間 來分配(剩余 1 bit),不夠大, // 舍棄(浪費)掉,再向內存申請 1 byte 的空間 來 存儲 c (剩余 3 bit 空間) char d : 4;// d 需要 4 bit 位,剩余內存空間(3 bit)不夠,把 3 bit 浪費掉(舍棄) // 再向內存申請 1 byte 空間,來存儲 d,(剩余 4 bit 空間) // 至此 數據全部 存儲完畢,剩余的空間 舍棄掉(浪費了) // 一共向內存 申請了 3 byte 的空間};int main(){ struct s s = { 0 }; s.a = 10;// 1010 因為 a 只有 3 bit 位 所以存入的是 010 s.b = 20;// 10100 因為 b 只有 4 bit 位 所以存入的是 0100 s.c = 3;// 0011 因為 c 只有 5 bit 位 所以存入的是 00011 s.d = 4;// 0100 因為 d 只有 4 bit 位 所以存入的是 0100 return 0;}
?
?
?
?
?
?
?
?
程序一:
enum sex// 性別{ // 枚舉的可能取值(枚舉常量) male,// 0 female,// 1 secret// 2};enum color // 顏色{ // 枚舉的可能取值(枚舉常量) red,// 0 green,// 1 blue// 2};int main(){ enum day d = mon;//枚舉賦的值,只能是 枚舉的 可能取值 enum sex s = male;//枚舉賦的值,只能是 枚舉的 可能取值 enum color c = blue;//枚舉賦的值,只能是 枚舉的 可能取值 blue 在枚舉的里面 是 2, 那我們 可不可以這樣寫 enum color c = 2 ? 答案是不行,右邊 2 是 int 類型, 左邊的 c 是 enum color 類型 printf("%d %d %d/n", male, female, secret);// 0 1 2 printf("%d %d %d/n", red, green, blue);// 0 1 2 printf("%d/n",sizeof(s)); // 枚舉大小為 4 byte ,為什么呢? 因為 枚舉常量 的類型是 整形, 那 s 就是整形變量,所以輸出為 4 return 0;}
?
?
程序二:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/119303.html
大家好,我們每天全網搜集各行各業的研究報告,了解一個行業從閱讀這個行業的研報開始,今日分享目錄如下: 20211006分享目錄: 2021抖音電商商家經營方法論白皮書-34頁.pdf 2021中國數據智能產業發展研究報告-50頁.pdf 2021公益數字化轉型-56頁.pdf 2021年中國一線城市出行平臺調研報告-77頁.pdf 2021年中國內容機構(MCN)行業發展研究報告-66頁.pd...
摘要:論壇下載由于庫是不帶中值濾波器的,需要自己實現,所以花了點時間制作了一個章節。紅色線是波形高斯白噪聲均勻白噪聲。第版教程發布中文顯示章節論壇下載可以直接運行界面效果,也可以使用可以直接編譯運行。上位機已經整合主機,下一版發布 往期周報匯總地址:http://www.armbbs.cn/for...
摘要:參一江湖只作為內容整理方,僅供學習使用。更多相關報告請查看參一江湖星球。 大家好,我們每天全網搜集各行各業的研究報告,了解一個行業從閱讀這個行業的研報開始,今日分享目錄如下: 20210906分享目錄: 2021中國車險科技創新服務研究報告-45頁.pdf 2021年中國家裝行業數字化研...
大家好,我們每天全網搜集各行各業的研究報告,了解一個行業從閱讀這個行業的研報開始,今日分享目錄如下: 20210928分享目錄: 休閑娛樂行業主題研究:本地出行,眾彩紛呈-35頁.pdf 休閑服務行業海南折扣觀察第一期:SKU較少的GDF折扣小幅加大,其他公司相對穩定-14頁.pdf 傳媒行業2021年中期策略報告:從流量到留量,抓住年輕人、擁抱視頻化、提升專業化-30頁.pdf 傳媒行業深度...
閱讀 3406·2021-11-25 09:43
閱讀 2294·2021-09-06 15:02
閱讀 3537·2021-08-18 10:21
閱讀 3339·2019-08-30 15:55
閱讀 2342·2019-08-29 17:06
閱讀 3533·2019-08-29 16:59
閱讀 960·2019-08-29 13:47
閱讀 2756·2019-08-26 13:24