1

我有一个 int64(它是一个 long long)值和一个字节值。我想将它们合并在一起。我知道我的 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

4

3 回答 3

3

You can use bitwise operators to achieve this. Let's say you want to sacrifice the 8 most significant bits in your long long. (Be careful if your long long is negative ! The sign is stored as the most significant bit, so you'll lose the sign !)

Now, to do this, you can do :

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)
}

For the little explanation, << is a bitshifting operator. What it does is that it shifts all your bits either right or left. Bits that goes out of boundaries are lost, and bits coming from nowhere are set to 0 :

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

In your case, we shift to the right of 8 bits (to leave space for your byte), and therefore the 8 most significant bits are lost forever. But now, we have something like :

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

Which means that we can add anything fitting in 8 bits without modifying the original value. And tada ! We have stored a byte in a long long !

Now, to extract the byte, you can just cast it as a char. During the cast, only the 8 least significant bits are saved (your byte).

And finally, to extract your long long, you just have to shift the bits the other way around. The byte will be overwritten, and your long long will be as good as new !

于 2013-07-04T15:51:39.067 回答
0

Just a hint about bit operations in 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 */

Same works with long or long long as well of course. I hope that helps you to understand how to use bit operations.

于 2013-07-04T15:52:21.107 回答
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]
);
于 2013-07-04T16:00:25.427 回答