C語言學習之聯合型別
前言
聯合(union)是一種特殊的資料型別,和結構體很像,結構體各成員變數有自己獨立的儲存位置,而聯合的成員變數共享同一片儲存區域,因此聯合變數再一個時刻只能儲存它的某一個成員的值。
聯合的定義和初始化
聯合的定義方式與結構體是一樣的,只是把關鍵字 struct 改成 union:
union [標籤名稱] { 成員宣告列表 };
下面的例子定義了一個名為Data的聯合型別,它有 3 個成員:i、x 和 str:
union Data { int i; double x; char str[16]; };
這種型別的物件可以儲存一個整數、一個浮點數或一個短字串。
下面的宣告定義了一個 union Data 型別的物件 var 和一個 unionData 型別的陣列 myData,它有 100 個元素(聯合的空間大小為它最大成員的空間大小):
union Data var, myData[100];
聯合成員值的獲取和修改
獲取聯合成員值的方式和獲取結構體成員的方式一樣。但是與結構體不同的是,當改變一個聯合成員的值時,實際上修改了該聯合所有成員的值。
聯合的初始化
與結構一樣,C99 允許在初始化器中使用成員指示符來指示哪個成員被初始化。而且,如果初始化器沒有成員指示符,那麼就與聯合內的第一個成員關聯。具有自動儲存類的聯合物件也可以使用已有的同類型物件來初始化。下面是一些初始化例子:
union Data var1 = { 77 }, var2 = { .str = "Mary" }, var3 = var1, myData[100] = { {.x= 0.5}, { 1 }, var2 };
陣列 myData 中的元素如果沒有指定初始化器,會被隱式地初始化為 0 值。
union的應用:浮點型轉換為4位元組整型
在串列埠、IIC、SPI等資料傳送時,基本上都是一次傳送一個位元組的資料,如果我們要傳送的是浮點型別的資料呢?常用的方法是將浮點數乘以一個倍數,如10,100,1000,10000等,然後將其轉換為整型資料再轉化為單個位元組進行傳送。如果這個資料是要進行顯示的話,那麼這樣做並沒有什麼不好。但是如果這個數是要傳輸給另端進行繼續計算的話,那麼就要考慮另一種方法了,就是直接將浮點資料轉換為4個單位元組,在另一端接受完資料後再轉化為浮點資料,這種方式不會造成精度的丟失,計算量也比較小。
【示例程式】:
#include <stdio.h> typedef union { float fdata;//fdata和ldata共用儲存空間 int ldata; } FloatLongType; //將浮點數f轉化為4個位元組資料存放在byte[4]中 void Float_to_Byte(float f,unsigned char byte[]) { FloatLongType fl; fl.fdata=f; byte[0]=(unsigned char)fl.ldata; byte[1]=(unsigned char)(fl.ldata>>8); byte[2]=(unsigned char)(fl.ldata>>16); byte[3]=(unsigned char)(fl.ldata>>24); } //將4個位元組資料byte[4]轉化為浮點數存放在*f中 void Byte_to_Float(float *f,unsigned char byte[]) { FloatLongType fl; fl.ldata=0; fl.ldata=byte[3]; fl.ldata=(fl.ldata<<8)|byte[2]; fl.ldata=(fl.ldata<<8)|byte[1]; fl.ldata=(fl.ldata<<8)|byte[0]; *f=fl.fdata; } int main() { float f=123456.781234;//要轉換的浮點數 unsigned char byte[4]= {0}; //轉換後的4個位元組資料存放的陣列 printf("float data=%f\n",f); //float 轉換為 4個位元組資料 Float_to_Byte(f,byte); //輸出轉換後的4個位元組資料 printf("%f to : %x %x %x %x \n", f, byte[0], byte[1], byte[2], byte[3]); //把byte的4個位元組資料轉換為float Byte_to_Float(&f,byte); printf("float data=%f\n",f);//輸出轉換後的結果 return 0; }
【輸出結果】:
float data=123456.781250 123456.781250 to : 64 20 f1 47 float data=123456.781250
可以看出,浮點型資料123456.781250
被轉換成了64-20-f1-47
,4個位元組的資料。
不使用聯合將單精度浮點型轉換成4個位元組
在使用微控制器和匿名上位機通訊,當傳輸的是一個float型別的資料時,我們需要將float型別資料轉換為4個位元組的char型別然後通過串列埠發出去才可以正常顯示,
以下是我寫的一個函式,不使用聯合,可以把一個浮點型資料轉換成4個位元組的資料,然後通過串列埠傳送出去:
//一個單精度浮點資料的傳送 void ANO_SendFloat(int channel, float f_dat) { u8 tbuf[8]; int i; unsigned char *p; for(i = 0; i <= 7; i++) tbuf[i] = 0; p=(unsigned char *)&f_dat; tbuf[0] = 0x88; tbuf[1] = channel;//0xA1 tbuf[2] = 4; tbuf[3]=(unsigned char)(*(p+3));//取float型別資料儲存在記憶體中的四個位元組 tbuf[4]=(unsigned char)(*(p+2)); tbuf[5]=(unsigned char)(*(p+1)); tbuf[6]=(unsigned char)(*(p+0)); for(i=0; i<=6; i++) tbuf[7] += tbuf[i];//校驗和 //printf("%s",tbuf);//串列埠傳送字串 }