2016-08-03 28 views
1

我陷入了一個試圖將一些變量打包成一個變量8字節長的陷阱。C++將不同的數據類型打包成一個長變量

基本上,我有幾個小的二進制大小的項目,我需要把它們放在一起發送到必須能夠解壓縮的類中。

所以,我提出以下幾點:

typedef unsigned long long PACKAGE; // 8 byte (shows as _int64 in debug) 
(sizeof returns '8') 
unsigned int dat1 = 25; // 1 byte long max 
unsigned int dat2 = 1; // 4 bit long max 
unsigned int dat3 = 100; // 2 byte long max 
unsigned int dat4 = 200; // 4 byte long max 
unsigned int dat5 = 2; // 4 bit long max 

然後我做封裝類型的變量,它是空的(0)

PACKAGE pack = 0; 

我想拋出使用二進制操作變量成包,我這樣做:

pack = (dat1 << 56) | (dat2 << 52) | (dat3 << 36) | (dat4 << 4) | dat5; 

它的工作只有一半好,我計算,我必須得到包的十進制值等於2526526262902525058,或

0010001100010000000001100100000000000000000000000000110010000010 

二進制,但是istead我得到588254914,或 00100011000100000000111011000010‬二進制 這是某種正確的在它的尾巴和頭,但中間部分地方缺少了。

當這樣做時,我仍然想要以某種方式提取數據。

+1

什麼,確切地說,你的問題是? –

+0

你可以使用'uint64_t'和一個位域結構的聯合?雖然打字就像打破了嚴格的走樣規則。 –

+0

一個由56個位置移動的int變量隱含地只將它移動了24個位置,這就解釋了爲什麼得到錯誤的答案。這是假設一個int是4個字節... – Madhusudhan

回答

2

我寧願使用一個bitfield結構來表示這種類型的(也可以使用uint64_t,以確保可用大小):

union PACKAGE { 
    struct bits { 
     uint64_t dat1 : 8; // 1 byte long max 
     uint64_t dat2 : 4; // 4 bit long max 
     uint64_t dat3 : 16; // 2 byte long max 
     uint64_t dat4 : 32; // 4 byte long max 
     uint64_t dat5 : 4; // 4 bit long max 
    }; 
    uint64_t whole; // for convenience 
}; 

正如comments提到你甚至可以使用uint_least64_t數據類型,以確保您的目標支持它(因爲uint64_t的可用性是從當前C++標準可選的):

union PACKAGE { 
    struct bits { 
     uint_least64_t dat1 : 8; // 1 byte long max 
     uint_least64_t dat2 : 4; // 4 bit long max 
     uint_least64_t dat3 : 16; // 2 byte long max 
     uint_least64_t dat4 : 32; // 4 byte long max 
     uint_least64_t dat5 : 4; // 4 bit long max 
    }; 
    uint_least64_t whole; // for convenience 
}; 
+0

未來的讀者:注意使用'uint64_t'。這種類型,如果你的編譯器支持,將保證一個無符號的64位整數。該定義可以在'' – user4581301

+0

@ user4581301中找到它實際上由標準支持。 –

+1

謝謝,我可能只是爲此而努力 - 只是需要花些時間來閱讀關於此事的內容,以前還沒有在位域上過關。 – jinxed

1

假設sizeof(unsigned int) != sizeof(unsigned long long),每個班次的左操作數是錯誤的類型。每個移位操作都被截斷(可能爲32位)。

嘗試,例如:

typedef unsigned long long PACKAGE; // 8 byte (shows as _int64 in debug) 
(sizeof returns '8') 
unsigned long long dat1 = 25; // 1 byte long max 
unsigned long long dat2 = 1; // 4 bit long max 
unsigned long long dat3 = 100; // 2 byte long max 
unsigned long long dat4 = 200; // 4 byte long max 
unsigned long long dat5 = 2; // 4 bit long max 

pack = (dat1 << 56) | (dat2 << 52) | (dat3 << 36) | (dat4 << 4) | dat5; 

或:

typedef unsigned long long PACKAGE; // 8 byte (shows as _int64 in debug) 
(sizeof returns '8') 
unsigned int dat1 = 25; // 1 byte long max 
unsigned int dat2 = 1; // 4 bit long max 
unsigned int dat3 = 100; // 2 byte long max 
unsigned int dat4 = 200; // 4 byte long max 
unsigned int dat5 = 2; // 4 bit long max 

pack = ((PACKAGE)dat1 << 56) | ((PACKAGE)dat2 << 52) | ((PACKAGE)dat3 << 36) | ((PACKAGE)dat4 << 4) | (PACKAGE)dat5; 

注:好,實際上每個移位操作,其中,右邊的操作數比左側的尺寸更大手部類型,以位爲單位調用未定義的行爲。典型的未定義行爲是截斷,但標準允許任何其他行爲,直至幷包括全局熱核戰爭。

+1

我會讓其他人回答如何使用位域。 –

+0

是的,sizeof(unsigned int)!= sizeof(unsigned long long) - 給我一點時間來試試,謝謝 – jinxed

+0

這兩種方式都可以工作,所以可能是在32位模式下編譯導致未定義行爲的問題?呃,這很方便。我可能會更好地嘗試看另一種方式,也許固定寬度整數或位域,如上面建議的那樣...... – jinxed

相關問題