2013-07-04 54 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

这是未定义的行为。在实践中,取决于字节顺序(取决于实际情况,它可能导致后来的崩溃等),它将取决于实现。 –