我正在尝试将现有应用程序从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通道。
以下测试程序证明我的RGB在使用GCC时都是紧凑的:
#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)
等等,但我发现没有组合将我的结构打包为三个字节的大小。
如何将我的应用程序移植到Microsoft的编译器,同时保持功能和与GCC的兼容性?
额外问题:如何在使用64位编译器(GCC或MSVC)编译时保留功能?
答案 0 :(得分:3)
this SO question和this question的答案提到了bit-packing is&#34;实现定义&#34;并导致this official MSVC documentation page说:
相邻位字段被打包到相同的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()不兼容,至少是直接。