2013-07-04 55 views
1

我有一個int64(這是一個long long)值和一個字節值。我想將它們合併在一起。我知道我長久的價值不使用64位。所以我想使用未設置的8位(最重要或最不重要?)來編碼一個字節。將一個字節組合成很長的長度

後來我想單獨找到原始值和字節。

所以優選功能或排序

typedef unsigned char byte; 
typedef long long int64; 

int64 make_global_rowid(int64 rowid, byte hp_id); 

byte get_hp_id(int64 global_row_id); 

int64 get_row_id(int64 global_row_id); 

get_hp_id的方式隔開的宏,並返回從合併數值的字節,而get_row_id返回其用字節合併

+3

多遠你走到這一步,你的編碼呢?附:你可以用&(和運算符)和位移來實現<<, >> – Bathsheba

+1

可能對'|'或運算符也是有用的......;) –

+0

函數名稱只是爲了闡明我想實現的內容。如果我知道該怎麼做,我就不會在這裏:-) – user1461001

回答

3

可以使用原來的int64按位運算符來實現這一點。假設你想犧牲你長久以來最重要的8個位。 (!要小心,如果你很長很長爲負的符號被存儲爲最顯著位,那麼你將失去標誌)

現在,要做到這一點,你可以這樣做:

byte get_hp_id(int64 global_row_id) 
{ 
    return ((char)global_row_id); 
} 

int64 get_row_id(int64 global_row_id) 
{ 
    return (global_row_id >> 8); 
} 

int64 make_global_rowid(int64 rowid, byte hp_id) 
{ 
    return (rowid << 8 + hp_id) 
} 

對於這個小小的解釋,<<是一個位移運算符。它所做的就是將所有比特向右或向左移動。這超出邊界丟失不知從哪兒來了位,和位被設置爲0:

1001001 << 2 == 0100100 // the first 1 is lost, and 2 "0" come from the right 

你的情況,我們轉移到8位​​(保留給你的字節的空間)的權利,因此, 8個最重要的位永遠丟失。 但是現在,我們有這樣的事情:

(xxxxxxxx)(xxxxxxxx)(xxxxxxxx)(00000000) 

這意味着我們可以在不修改原始值添加任何東西在8位接頭。和tada!我們已經存儲了一個很長的字節!

現在,爲了提取字節,你可以將它轉換爲字符。在演員陣營中,只有8個最不重要的位被保存(你的字節)。

最後,爲了提取你的長時間,你只需要反過來移動位。該字節將被覆蓋,並且您的漫長長度將會像新的一樣好!

+0

'來自無處的位被設置爲0':這對'<<'是正確的,但不一定對於'>>'。如果所有的值都保證是非負的,像這樣的東西可以工作。另一方面,如果可能存在負面情況,則會變得更加複雜。 –

+0

無論使用什麼班次,我都認爲數值填充了0。爲什麼'''''''有所不同?至於否定性,我會編輯提及它:) – ChristopheLec

+0

我剛剛測試過,它用gcc編譯時填充0。它依賴於系統嗎? (我也瞭解到,移動變量的大小(例如移動一個32位的int32)會觸發一個編譯警告,並且在這種情況下不會進行移位。奇怪...) – ChristopheLec

0

僅有約在C位操作提示:

int i = 0x081500; //lsb is 0x00 
    char b = '\x12'; //any byte 
    char r; 

    i = i | (b & 0xff);  // will be 0x081512 
    r = i & 0xff; // again 0x12, equal to r 

    i = i | ((b & 0xff) << 16); // will be 0x120815000 because first b is shifted 16 bits (--> 0x120000) 
    r = (i >> 16) & 0xff; // first i is shifted to 0x12, then use lsb 
    /* important: this expects i >= 0 */ 

作品一樣長或者很長很長,以及課程。我希望這可以幫助你理解如何使用位操作。

+1

'>>'不是嚴格指定的簽名。 –

+0

@Jams Kanze:你當然是對的。用0xff掩蓋b應該這樣做。我已經相應地編輯了我的代碼 –

+0

@James我最好在回答之前仔細閱讀(在這裏遲到:-)。儘管如此,你是對的。該代碼是一個例子,如何位操作的工作,我會添加一個評論,「我」是要例外「= 0 –

0

,易於使用的緣故,我會用一個聯合:

union longlong_and_byte { 
    long long long_value; 
    char char_values[8]; 
}; 

union longlong_and_byte test; 

test.long_value = 4000; 

// for little endian (x86 for example) the most significant byte is the last one 
test.char_values[7] = 19; 

// for big endian (PPC for example) the most significant byte is the first one 
test.char_values[0] = 19; 


printf("long long value is %ld\nchar value is %d\n" 
, test.long_value & 0xFFFFFFFFFFFFFF // need to mask off the necessary bits, only works with unsigned 
, test.char_values[7] 
); 
+0

這是未定義的行爲。在實踐中,取決於字節順序(取決於實際情況,它可能導致後來的崩潰等),它將取決於實現。 –