我有一个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
答案 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]
);