結構的大小

2021-05-06 17:12:01 字數 3282 閱讀 4440

很多同學對一些型別的大小不是很重視,其實這些都是很重要的東西,

尤其是c,因為c的指標使用非常多,不知道型別、結構的大小,怎麼控制記憶體?

當然準確的位元組數依賴於機器和編譯器。我們今天講的是我們常用的win32

首先我們要搞明白b和b的區別:b是bit(位)。b是byte(位元組)。1b = 8b

char 1b

short 2b

int 4b

long 4b

float 4b

double 8b

指標都是 4b

這些東西揹著就行了。

由於不同的平台其大小也不一樣,故我們常使用巨集定義,或者typedef。

如:typedef char int8;

typedef unsigned char uint8;

typedef short int16;

#define int8 char

#define uint8 unsigned char

#define int16 short

定義時使用

int8 a;

uint8 b;

int8 c;

這樣在針對不同的平台使用不同的typedef,

如何根據不同的平台使用不同的typedef也可以用巨集來實現,這裡不再闡述,或者改動少量**。

下面的結構大小的問題就有的複雜了。

struct s

sizeof(s) = ?

初學者一看char 1;int 4;加起來是5。

可能你是對的,但大部分情況下你是錯的。

其實sizeof(s) = 8;在這裡有個位元組對齊的機制。

下面先看乙個我的同事在工作中遇到的乙個bug。

func(uint8 *pdata)

同學們知道可能的原因嗎。

這就要用位元組對齊來解釋了。簡單點說就是:

讓寬度為1的基本資料型別(char 等)都位於能被1整除的位址上,

讓寬度為2的基本資料型別(short等)都位於能被2整除的位址上,

讓寬度為4的基本資料型別(int  等)都位於能被4整除的位址上,以此類推。

本來uint8*的pdata是乙個被1整除的位址,現在將它賦值給乙個應該被4整除的位址。

有的平台可以正常執行,但有的平台就會進行檢查,

你在操作乙個只能被1整除位址上的寬度為4的資料時就宕機了。

然而為什麼需要位元組對齊?這樣有助於加快計算機的取數速度。

關於怎麼計算結構體的大小,前人有如下總結:

1) 結構體變數的首位址能夠被其最寬基本型別成員的大小所整除;

2) 結構體每個成員相對於結構體首位址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充位元組(internal adding);

3) 結構體的總大小為結構體最寬基本型別成員大小的整數倍,如有需要編譯器會在最末乙個成員之後加上填充位元組(trailing padding)。

這樣我們看下面的結構:

struct s1

sizeof( s1 ) = 8;//根據上面的總結很容易算出來。

了解了這個我們在定義我們的結構的時候就可以注意我們的寫法是可以節約空間的。

例如:struct s1

;就可以寫成

struct s1

;節約了4個位元組。

下面我們再看這個結構的大小

struct s2

;//呵呵有的複雜了把。

像這種結構裡面套有結構的情況,我們要將s1拆分開來看,s1裡面最大是int,a和int對齊,1+3.s1是8.加上b和對齊,1+3.共16.

但這並不是總是這樣,有時我們需要改變對齊的方式,這裡有兩個編譯命令#pragma pack(n)和align(n)

#pragma pack(n) //n的合法值包括(1,2,4,8,16)他和編譯開關/zpn是乙個意思(如果不知道什麼是編譯開關可以到網上搜)。

意思就是對齊值取min( n, sizeof( member ) )

舉個例子:

#pragma pack(push)//儲存之前的pack

#pragma pack(2)//設定當前的pack

struct s1

;#pragma pack(pop)//恢復之前的pack

大小的計算:char型的a和要對齊的min( 2, sizeof(int) ),1+1;int型b是4;同樣c和要對齊值共2;此時是sizeof( s1 ) == 8,

align(n)//n的合法值是2的倍數(2,4,8,...)指此結構的大小是max( n, size(member) )的倍數。

__declspec(align(32)) struct s1

;前面還是和上面的一樣排序,但到最後乙個char型的c時後面要填充滿32個位元組。sizeof(s1) == 32.

有個問題要注意。空結構的大小不是0.而是1.

struct s

;sizeof( s ) == 1;

當然如果你定義

__declspec(align(32)) struct s1

;大小就是32。

在結構中我們還有一種常用的用法。按位來訪問資料。

struct s

;我來畫個圖把,直接明了。

|1    |2    |3    |4    |5    |6    |7    |8   |           //對齊int

|1 e1 |2 e2 |3 e3 |4    |5    |6    |7    |8   |…………|31  |32  |

|1 f1 |2    |3    |4    |5    |6    |7    |8   |

|1    |2    |3    |4    |5    |6    |7    |8   |          //下面的都是對齊

|1    |2    |3    |4    |5    |6    |7    |8   |

|1    |2    |3    |4    |5    |6    |7    |8   |

我不多說了,多多揣摩。

結構體的大小

對齊 現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定變數的時候經常在特定的記憶體位址訪問,這就需要各型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。對齊的作用和原因 各個硬體平台對儲存空間的處...

結構體的大小

typedef 定義型別 typedef unsigned long long uint64 定義型別,起外號 例如 typedef struct student student 注意 typedef int pfun int,int 函式指標 指向函式的指標 typedef int pint de...

結構體的大小

結構體中的成員可以是不同的資料型別,成員按照定義時的順序依次儲存在連續的記憶體空間。和陣列不一樣的是,結構體的大小不是所有成員大小簡單的相加,需要考慮到系統在儲存結構體變數時的位址對齊問題。看下面這樣的乙個結構體 struct stu1 先介紹乙個相關的概念 偏移量。偏移量指的是結構體變數中成員的位...