1.結(jié)構(gòu)體內(nèi)存分析
- 1.結(jié)構(gòu)體存儲原理
- 內(nèi)存是以字節(jié)為單位編號,但一些硬件平臺對某些特定類型的數(shù)據(jù)只能從某些特定地址開始, 比如從偶地址開始。若不按照適合其平臺的要求對數(shù)據(jù)存放進行對齊,會影響到效率。 因此,在內(nèi)存中,各類型的數(shù)據(jù)是按照一定的規(guī)則在內(nèi)存中存放的,這就是對齊問題。
- 結(jié)構(gòu)體占用的內(nèi)存空間是每個成員占用的字節(jié)數(shù)之和(考慮對齊問題)
- 2.結(jié)構(gòu)體變量占用存儲空間大小
注:定義結(jié)構(gòu)體類型不分配存儲空間,定義變量時才分配存儲空間
- 規(guī)則一:找到結(jié)構(gòu)體中占用字節(jié)數(shù)最大的類型,假設其占用的字節(jié)數(shù)為8,每次開辟新的存儲空間都增加8.
- 規(guī)則二:結(jié)構(gòu)體中每條數(shù)據(jù)按定義類型時的順序存儲,一條數(shù)據(jù)能存的下就往里存,存不下就開辟新的內(nèi)存空間
??:
#include <stdio.h>
int main(int argc, const char * argv[]) {
//定義結(jié)構(gòu)體類型,這里的結(jié)構(gòu)體類型Person中,占用字節(jié)數(shù)最大的數(shù)據(jù)類型為double(64位編譯器下占用8個字節(jié)),在存儲score、height、age時,存儲空間不夠的情況下,每次都會新開辟8個字節(jié).
/*
struct Person {
short score;
int age;
double height;
};
//定義結(jié)構(gòu)體變量
struct Person sp = {99,18,178.0};
printf("調(diào)整順序前------%lu\n",sizeof(sp));
*/
//調(diào)整結(jié)構(gòu)體類型數(shù)據(jù)的順序
struct Person {
short score;
double height;
int age;
};
struct Person sp = {99,178.0,18};
printf("調(diào)整順序后------%lu\n",sizeof(sp));
return 0;
}
//輸出:
調(diào)整順序前------16
調(diào)整順序后------24
存儲空間大小不同的原因與結(jié)構(gòu)體數(shù)據(jù)的順序有關,例子中,最關鍵的是第二個數(shù)據(jù)的存儲,調(diào)整前第二個數(shù)據(jù)為int類型,由于變量存儲時一次開辟sizeof(double) = 8;short占用了其中的兩個字節(jié),剩余的6個字節(jié)能夠存儲int的4個字節(jié),所以不會開辟新的存儲空間,而調(diào)整后第二個數(shù)據(jù)為double,剩余的6個字節(jié)不夠存儲double,所以開辟了新的存儲空間8個字節(jié).所以調(diào)整前存儲一個結(jié)構(gòu)體變量需要16個字節(jié),而調(diào)整后需要24個字節(jié)
2.指向結(jié)構(gòu)體變量的指針
// 定義一個結(jié)構(gòu)體類型
struct Student {
char *name;
int age;
};
// 定義一個結(jié)構(gòu)體變量
struct Student stu = {“sj", 25};
// 定義一個指向結(jié)構(gòu)體的指針變量
struct Student *p;
// 指向結(jié)構(gòu)體變量stu
p = &stu;
/*
這時候可以用3種方式訪問結(jié)構(gòu)體的成員
*/
// 方式1:結(jié)構(gòu)體變量名.成員名
printf("name=%s, age = %d \n", stu.name, stu.age);
// 方式2:(*指針變量名).成員名
printf("name=%s, age = %d \n", (*p).name, (*p).age);
// 方式3:指針變量名->成員名
printf("name=%s, age = %d \n", p->name, p->age);
return 0;
}