簡體   English   中英

如何在Visual Studio中將結構壓縮為包含uint32_t的24位?

[英]How to pack a struct in Visual Studio to 24 bits that contains an uint32_t?

我試圖將現有應用程序從32位ARM微控制器移植到Microsoft Windows等桌面平台。 GCC用於ARM,我可以使用32位MinGW編譯器在Windows上成功編譯應用程序,但是我使用Microsoft的Visual Studio編譯器沒有成功,這就是我在這里尋求幫助的原因。

這是我的應用程序正在做的事情:

我有一些每個像素三個字節組成的幀緩沖區,所以我的內存看起來像RGBRGBRGB等。 我在ARM上使用DMA通道將像素推出顯示器,並且我的顯示器直接了解此內存布局。

我還想節省一些CPU周期,所以我想使用ARM的飽和ADD __UQADD8繪制我的幀緩沖區,並使用單個操作在所有三個通道上執行飽和加法。

為此,我需要所有三個通道都在單個整數中可用,以用作__UQADD8參數。

這就是為什么我對幀緩沖區的一個像素使用並集的原因,因為它提供了一個包含R,G,B的結構作為uint8_t並提供與24位寬的整數標記數據相同的內存,從而可以訪問單獨的通道:

union Rgb {
    struct {
        uint8_t r;
        uint8_t g;
        uint8_t b;
    } ch;
    unsigned int data : 24 __attribute__((__packed__));
}

24位的寬度和打包的屬性被添加到數據整數,以將整數的寬度限制為三個字節。 然后,我可以像這樣使用像素中的數據:

Rgb Rgb::operator+(const Rgb & op) {
    __UQADD8(data, op.data);
    return Rgb(data);
}

請注意, __UQADD8神奇地僅寫入了我的整數的四個字節中的三個字節,並且不會更改幀緩沖區中下一個RGB的R通道。

以下測試程序證明了使用GCC時,我的RGB都包裝緊密:

#include <iostream>
#include <stdint.h>

union Rgb {
struct {
                uint8_t r;
                uint8_t g;
                uint8_t b;
        } ch;
    unsigned int data : 24 __attribute__((packed));
} ;

int main()
{
    std::cout << "Sizeof(Rgb) = "  << sizeof(Rgb) << std::endl;
    return 0;
}

要使用MSVC編譯示例,必須刪除__attribute__packed。 該程序運行,但給出4作為輸出。 MSVC中還有許多其他可以使用的屬性,包括#pragma pack ,未對齊的指針__attribute__(aligned)等等__attribute__(aligned) ,但我發現沒有組合可以將結構壓縮為三個字節。

如何在保持功能和與GCC更好的兼容性的同時將我的應用程序移植到Microsoft的編譯器?

額外的問題:使用64位編譯器(GCC或MSVC)進行編譯時,如何保持功能?

這個SO問題這個問題的答案都提到了“實現定義”的位打包,並導致該MSVC官方文檔頁面顯示:

相鄰的位字段打包到相同的1、2或4字節分配單元中...

因此,看來您無法在MSVC中獲得確切的3字節位字段。 我唯一想到的替代方法是執行以下操作:

#pragma pack(push, 1)
union Rgb {
     struct {
          uint8_t r;
          uint8_t g;
          uint8_t b;
     } ch;
    unsigned char data[3];
};
#pragma pack(pop)

這將為您提供所需的3字節聯合大小,但至少與直接使用__UQADD8()可能不兼容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM