繁体   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