将一个字节组合成long long

时间:2013-07-04 15:29:49

标签: c++ c bit-manipulation

我有一个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返回与字节合并的原始int64

3 个答案:

答案 0 :(得分:3)

您可以使用按位运算符来实现此目的。假设您想要牺牲长期中最重要的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位的内容而无需修改原始值。和田田!我们已经存储了一个很长的字节!

现在,要提取字节,您只需将其转换为char即可。在演员表中,只保存了8个最低有效位(你的字节)。

最后,为了提取你的长期,你只需要反过来改变这些位。该字节将被覆盖,您的长期将与新的一样好!

答案 1 :(得分: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 */

同样适用于长或长也是如此。我希望这有助于您了解如何使用位操作。

答案 2 :(得分: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]
);