結構體 聯合體的應用,以及位元組對齊和位元組序的問題

2021-09-30 04:52:49 字數 2322 閱讀 6369

通訊中,用過的非常多。給你乙個我的例子

typedef union

complex;

float64     dfval;

prot_time   time;

}protevent_valtype;   

//不同型別的數值

typedef

struct

head;

uint8    name[var_comm_size];

}protmsg_event_par;

對於那種乙個整數和幾個位元組取值的問題,建議不要用結構聯合來實現。如:

union bits32

byte;};

這個在不同的cpu架構變現不相同,就是cpu的高低次序問題。在普通的pc即x86cpu上,是小頭在前,即c1對應的num的第乙個位元組,但是在其它一些如powerpc、sun的sparc架構cpu上,是大頭在前,c1就對應num的第4個位元組。

在網路傳輸中,對這個問題很敏感,就是發生的位元組次序問題。在tcp/ip中,規定是網路次序,具體參考一下tcp/ip的資料。裡面有不少網路次序資料和本機資料的轉換問題。

為了避免這種問題,我們一般在通訊中,採用的是移位操作。如

/*****整數和單位元組數轉換操作,通過移位避開次序問題****

*/#define

byte0(intval) ( (uint8)(  0x000000ff&(intval)) )

#define

byte1(intval) ( (uint8)(( 0x0000ff00&(intval))>>8) )

#define

byte2(intval) ( (uint8)(( 0x00ff0000&(intval))>>16) )

#define

byte3(intval) ( (uint8)((0x0ff000000&(intval))>>24) )

/*******************位元組組合定義******************

*/#define

uint16comb(b1,b0)    ( (uint16)(b0) | (((uint16)(b1))<<8) )

#define

int16comb(b1,b0)    uint16comb(b1,b0)

#define

uint32comb(b3,b2,b1,b0)            /

(   (uint32)(b0)    /

|(((uint32)(b1))

<<

8)    /

|(((uint32)(b2))

<<

16)    /

|(((uint32)(b3))

<<

24) )

#define

int32comb(b3,b2,b1,b0)    uint32comb(b3,b2,b1,b0)

使用時,可以用:

c1=byte0(num);c2=

byte1(num);

...num

=uint32comb(c3,c2,c1,c0);

實際上移位操作,對於cpu來說,基本上是乙個指令週期,比你直接用struct和union還要快。這個問題涉及到32位cpu的整字對齊和整字操作處理問題和cpu的指令優化,具體可以去參考cpu指令的書籍。

對齊規則由編譯選項決定的,一般編譯器採用預設的編譯選項。一般儲存單元按照cpu的字長對齊,對於目前32位主流系統,基本的資料型別char、short、int、float,對齊在整字的開始。

如struct

;c占用第乙個字長的第乙個位元組,而後面的3個位元組變長儲存空洞;i和f各佔1個字長。

struct

;這種情況下,c1將分配在c之後,佔乙個位元組,而c1後面就留出來2各空洞。

所以在組織struct或者class時,注意一下成員分布的合理,綜合一下儲存分配情況。但是從cpu的指令操作上看,cpu一般按照乙個字長來執行,操作乙個int數要比乙個char效率高。也就說說,當cpu讀取乙個char數時,cpu先從記憶體中讀取一整個字長值到暫存器中,然後將相應char所在的那個位元組提取出來,從而完成乙個char的取值。

另外:程式設計時千萬注意float *pfval;指標的使用,浮點數指標一定要指向乙個整字起始的記憶體位置,如上面的&c1位址,否則在一些特定的cpu或微控制器中,對非對齊的浮點指標操作,會發生崩潰問題,這個和浮點指令的相容性問題。典型的是在sun的sparc、powerpc的一些cpu上就會發生崩潰問題。

想改變編譯器的對齊規則,可以在**中加入:

#pragma pack(push, 1)

.....//**

#pragma pack(pop)

聯合體,位域, 結構體對齊

聯合體union 當多個資料需要共享記憶體或者多個資料每次只取其一時,可以利用聯合體 union 在c programming language 一書中對於聯合體是這麼描述的 1 聯合體是乙個結構 2 它的所有成員相對於基位址的偏移量都為0 3 此結構空間要大到足夠容納最 寬 的成員 1下面解釋這四...

結構體聯合體

在c中,結構也是一種資料型別,可以使用結構變數,因此,象其它型別的變數一樣,在使用結構變數時要先對其定義。定義結構變數的一般格式為 struct 結構名 結構變數 結構名是結構的識別符號不是變數名。型別為第二節中所講述的五種資料型別 整型 浮點型 字元型 指標型和無值型 構成結構的每乙個型別變數稱為...

聯合體加結構體的應用

因為最近設計到通訊協議。而通訊協議中為了減少資料量,常常用乙個位元組的八個位分別代表八種不同的狀態。這就涉及到位的操作和分解。過程可能比較麻煩而且如果位數多的表示可能不是很明了,比如我乙個位元組的前三個位元組表示狀態,後面的分別乙個位元組表示其他情況 所以這邊利用了聯合體和結構體的綜合應用。用乙個結...