【发布时间】:2015-04-06 18:32:19
【问题描述】:
我正在尝试将现有应用程序从 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位的宽度和packed属性添加到数据整数中,将整数的宽度限制为三个字节。然后我可以像这样使用像素中的数据:
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)进行编译时保留功能?
【问题讨论】:
标签: c visual-studio struct unions bit-fields