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);		//串口發送字符串
}

參考資料:

歷史精選文章:


歡迎大家關注我的個人博客

或微信掃碼關注我的公眾號


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM