2015-04-06 34 views
2

我試圖將現有的應用程序從32位ARM微控制器移植到桌面平臺,如Microsoft Windows。 GCC在ARM上使用,我可以使用32位MinGW編譯器在Windows上成功編譯應用程序,但是我沒有成功使用Microsoft的Visual Studio編譯器,這就是我在這裏尋求幫助的原因。如何將Visual Studio中的結構打包爲包含uint32_t的24位?

這裏是我的應用程序是這樣做的:

我有一些幀緩衝由每像素三個字節,所以我的記憶中的樣子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)等等,但是我發現沒有組合將我的結構打包爲3字節的大小。

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

紅利問題:如何在使用64位編譯器(GCC或MSVC)進行編譯時保持功能?

回答

3

this SO questionthis question提及比特填料是「實現定義」而導致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()兼容,至少直接。

相關問題