許多計算機系統對基本數據型別的合法地址做出了一些限制,要求某種型別物件的地址必須是某個值K(通常是2,4,8,或16)的倍數。這種對齊限制簡化了形成處理器和記憶體系統之間介面的硬體設計。(來源於計算機操作系統第一部分,程式結構和執行)
其中詳細解釋參考大神部落格
https://blog.csdn.net/lgouc/article/details/8235471
1、利用預設規則
例1:
//程式碼1 共佔用 2 * sizeof(int) 個位元組
struct test
{
char a;
char b;
int num;
}
程式碼1 變數記憶體分佈如圖
預設情況下以 int 型變數 的位元組數(K值)進行對齊。
因爲char 型別只佔用了一個位元組,所以佔1格,int 型需要4個位元組,佔了4格
所以整個test 結構體需要8個位元組。
例2:
//程式碼2 共佔用 3 * sizeof(int) 個位元組
struct test
{
char a;
int num;
char b;
}
程式碼2 變數記憶體分佈如圖
總結:
在使用gcc編譯時,由於結構體內變數按照先後順序在記憶體中儲存,且按照預設規則以4進行對齊。要求結構體起始地址必須是4的倍數。在儲存char 型別後,儲存int 型別時仍然要求起始地址爲4的倍數,所以char 型別後的地址就不滿足儲存要求。所以char 型別後空了3個位元組。所以這就是程式碼2的記憶體分佈原因。
程式碼1的在儲存char型別後,下一個還是char型別。只有一個位元組,所以第一個char 型別後的地址是滿足儲存要求的。所以分佈如程式碼1下的圖示所示。
類似的程式碼和實際運算結果展示:
#include <stdio.h>
struct ffe
{
char a; //佔用4個位元組 實際使用1個位元組
int b; //佔用4個位元組 實際使用4個位元組 ,和char 變數共用8個位元組
double c; //佔用8個位元組 實際使用8個位元組
};
int main()
{
ffe tr;
printf("%d\n",sizeof(tr));
printf("a = %p\n, b = %p\n, c = %p\n",&tr.a, &tr.b, &tr.c);
return 0;
}
輸出結果:
16 a = 0x7ffcbf14ca00 , b =0x7ffcbf14ca04, c = 0x7ffcbf14ca08
記憶體中分佈大概如圖示
當變數位置交換後,實際佔用記憶體爲 3 * sizeof(double)。 一般爲24位元組。
struct ffe
{
char a; //佔用8個位元組,實際使用1個位元組
double c; //佔用8個位元組,實際使用8個位元組
int b; //佔用8個位元組,實際使用4個位元組
};
所以根據變數位元組大小來決定變數順序可以有效減小使用記憶體。
2、設定結構體記憶體對齊K值
使用如下語句
#pragma pack(k) //沒有分號
對應程式碼1,如果將k 設定爲1,則實際記憶體佔用爲6個位元組。將K設定爲2 ,結果也是一致的。因爲設定了變數的變數的對齊爲2的倍數。但整型變數實際佔用了兩個記憶體單元。會造成取值速度下降。
K = 4 的結果與程式碼1的結果是一致的。
當K = 8 超過了預設的 K =4 (int 4個位元組)。記憶體對齊仍然是按照 K = 4 進行記憶體對齊的。
位域:描述的是結構體中變數佔的位。(一個位元組共有8個位)
char 型別,一個位元組 ,共有8個位,所以位域數不能超過8。
int 型別 ,4個位元組,共有32個位,所以位域數不能超過32。
具體使用
//程式碼3
struct ffe
{
char a:2;
char b:2;
char c:2;
};
由於一個位元組(8個位)是系統中最小可定址單位。所以無法對位域取地址。無法通過地址檢視相關關係。
程式碼3的結構體,佔用記憶體爲一個位元組。由於一個字元變數只使用了兩個位,表示的最大字元ASCII碼不能超過3;因爲超過了就會溢位。
但是變數仍然滿足記憶體對齊規則。程式碼4的結構體仍然佔據8個位元組。
//程式碼4
struct ffe
{
char a:2;
char b:2;
char c:2;
int d:1;
};
只能通過大小或者賦值去判斷。
struct ttr
{
int a:8;
int b:8;
int c:8;
int d:8;
};
union ffe
{
int a;
ttr ch;
};
整型變數a 和結構體變數ch 共同佔據同一塊記憶體,兩種型別的記憶體大小是一致的,地址是一致的。存取變數按照正常存取即可,所以可以通過兩種型別存取同一塊記憶體 。將較小的值限制在相應的小空間內。達到節約記憶體的目的。所以賦值不能超過實際的位。