資料結構型別(記憶體篇)超全結構體,聯合,列舉記憶體解釋(適用c語言入門)
一.結構體的記憶體
記憶體對齊
規則:
1.結構體的第一個資料成員存放的地址為結構體變數偏移量為 0 的地址處.
2.其他起始地址為該型別變數所占記憶體的整數倍,如果不足部分用資料填充到所占記憶體的整數倍
3.結構體所占總記憶體為該結構體的成員中基本資料型別占位元組數最大的整數倍
(見圖解1-1)
#include<stdio.h>
struct str1 { // ??
char a; // 1 byte //此處若洗掉char a 則所占記憶體為 24 以驗證規則 1;(自行驗證)
int b; // 4 byte
float c; // 4 byte
double d; // 8 byte(最大)
char ch; // 1 byte
}s1; // 32 byte
//將結構體內部變數調換位置后結構體記憶體占用發生改變
struct str2 { // ??
char a; // 1 byte
char ch; // 1 byte
int b; // 4 byte
float c; // 4 byte
double d; // 8 byte(最大)
}s2; // 24 byte
int main() {
printf("%d\n",sizeof(s1)); //輸出結果:32
printf("%d\n",sizeof(s2)); //輸出結果:24
return 0;
}
圖解1-1

如果結構體內部含有陣列:(見圖解1-2)
#include<stdio.h>
// 當結構體成員包含陣列:
struct str3 {
int a; // 4 byte
double b; // 8 byte(最大)
char arr[9]; // 9 byte(char基本資料型別占 1byte)
}s3; // 結果:32
struct str4 {
double b; // 8 byte(最大)
int a; // 4 byte
char arr[9]; // 9 byte(char基本資料型別占 1byte)
}s4; // 結果:24
int main() {
//如果結構體成員含有陣列:
printf("%d\n", sizeof(s3)); //輸出結果:32
printf("%d\n", sizeof(s4)); //輸出結果:24
return 0;
}
圖解1-2

如果結構體中包含結構體:
#include<stdio.h>
struct str5 {
char ch;
short sh;
int num;
}s5;
struct str6 {
int n;
struct str5 s5;
}s6;
struct str7 {
int n;
char ch;
short sh;
int num;
}s7;
int main() {
//如果結構體成員包含結構體:
printf("%d\n", sizeof(s5)); //輸出結果:8
printf("%d\n", sizeof(s6)); //輸出結果:12 --> sizeof(int)+8
printf("%d\n", sizeof(s7)); //輸出結果:12
return 0;
}
結論:結構體 str6 和 str7等價,當結構體中成員包含結構體時 等價于 把成員結構體內容展開
注意:結構體成員包含的結構體不能為本身!
[完整代碼如下]
#include<stdio.h>
struct str1 { // 內部求和為 18byte
char a; // 1 byte
int b; // 4 byte
float c; // 4 byte
double d; // 8 byte(最大)
char ch; // 1 byte
}s1; // 結果:32 byte
// 將結構體成員變數調換位置后結構體記憶體占用發生改變:
struct str2 { // 內部求和為 18byte
char a; // 1 byte
char ch; // 1 byte
int b; // 4 byte
float c; // 4 byte
double d; // 8 byte(最大)
}s2; // 結果:24 byte
// 當結構體成員包含陣列:
struct str3 {
int a; // 4 byte
double b; // 8 byte(最大)
char arr[9]; // 9 byte(char基本資料型別占 1byte)
}s3; // 結果:32
struct str4 {
double b; // 8 byte(最大)
int a; // 4 byte
char arr[9]; // 9 byte(char基本資料型別占 1byte)
}s4; // 結果:24
// 當結構體成員包含結構體:
struct str5 {
char ch;
short sh;
int num;
}s5;
struct str6 {
int n;
struct str5 s5;
}s6;
struct str7 {
int n;
char ch;
short sh;
int num;
}s7;
int main() {
printf("%d\n",sizeof(s1)); //輸出結果:32
printf("%d\n",sizeof(s2)); //輸出結果:24
printf("\n");
//如果結構體成員含有陣列:
printf("%d\n", sizeof(s3)); //輸出結果:32
printf("%d\n", sizeof(s4)); //輸出結果:24
printf("\n");
//如果結構體成員包含結構體:
printf("%d\n", sizeof(s5)); //輸出結果:8
printf("%d\n", sizeof(s6)); //輸出結果:12
printf("%d\n", sizeof(s7)); //輸出結果:12
return 0;
}
二.聯合體的記憶體
規則:
1.大小必須足夠容納最寬的成員
2.大小能夠被它所包含的所有的基本資料型別的大小整除
#include<stdio.h>
union MyUnion1{
char s[9]; // 9 byte (char型別為 1 byte)
int n; // 4 byte
double d; // 8 byte
}; // 16 byte
union MyUnion2 {
char s[5]; // 5 byte
int n; // 4 byte
double d; // 8 byte
}; // 8 byte
int main() {
printf("%d\n", sizeof(MyUnion1)); // 結果:16
printf("%d\n", sizeof(MyUnion2)); // 結果:8
}
三.列舉的記憶體
#include<stdio.h>
enum Enum {
Enum1, // (int) 4 byte
Enum2, // (int) 4 byte
Enum3 // (int) 4 byte
}MyEnum;
int main() {
printf("%d\n", sizeof(MyEnum)); // 結果:4
printf("%d\n", sizeof(Enum1)); // 結果:4
printf("%d\n", sizeof(Enum2)); // 結果:4
printf("%d\n", sizeof(Enum3)); // 結果:4
return 0;
}
關于列舉的解釋大多數為:列舉皆為4位元組;(例:如上情況)
——關于列舉記憶體的問題不必太深究,但是想探一探,
標準C語言描述沒有明確規定列舉型別占用空間的大小,表示:“列舉型別的尺寸是以能夠容納最大列舉子值的整數的尺寸”,同時標準中也說明了: “列舉型別中的列舉子的值必須 能夠 用一個int型別表述.”
#include<stdio.h>
enum Enum {
Enum1 = 0x7f7f7f7f7f, // (int型別最大值) (int) 4 byte
Enum2, // (int) 4 byte
Enum3, // (int) 4 byte
Enum4 = 5,
Enum5,
Enum6 = 0x7f7f7f7f7f, //(int型別最大值)
Enum7
}MyEnum;
int main() {
printf("%d\n", sizeof(MyEnum)); // 結果:8
printf("%d\n", sizeof(Enum1)); // 結果:8
printf("%d\n", sizeof(Enum2)); // 結果:8
printf("%d\n", sizeof(Enum4)); // 結果:4
printf("%d\n", sizeof(Enum5)); // 結果:4
printf("%d\n", sizeof(Enum6)); // 結果:8
printf("%d\n", sizeof(Enum7)); // 結果:8
return 0;
}
當列舉子值超過 int 范圍時 得到列舉位元組占用為 8 byte
本以為是列舉定義為 long 型別尺寸,但是發現子值的輸出并非正確數值輸出,依舊溢位;
此處可能與 int 型別的大小有關:
(關于 int 型別)其大小為計算機的字長,與cpu暫存器位數相關
一般情況:32位計算機為4位元組 64位計算機為8位元組
但在 x64 計算機環境除錯結果多數仍然為4位元組可能和編譯器等多方面條件有關,
搜索資料中發現這樣一篇文章:https://blog.csdn.net/HES_C/article/details/88668276
按照c語言描述可以實作,但本人未能實作,查詢整理得到另一些合理解釋:
具體內容如下:
1.轉載:https://embedded.fm/blog/2016/6/28/how-big-is-an-enum
2.來自知乎留言:

enum本身并不以變數的方式存盤到記憶體當中,但是將enum本身作為變數(包括指定具體是哪個列舉值),因為這個變數包含了列舉型別中的一部分值,所以會分配空間,這個具體值的大小,應該和機器、列舉值指定值有關系,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/251765.html
標籤:其他
上一篇:2021-01-22總結
下一篇:自我介紹
