假设我有2个64位无符号整数。我有一个大小为110......
的窗口,它一次从第一个整数的末尾开始,到第二个整数的开头结束。 (当然,我知道它从哪里开始)
例如,第一个是0
,第二个是10
,窗口从第一个0110011 110
开始,窗口大小为0110011 and 110.......
。输出应为{{1}}。
我的问题是,如何编写这样一个体面的程序来解决这个问题?我尝试使用掩码,然后意识到我有2个块位整数({{1}}),我不知道如何将它们连接在一起。
答案 0 :(得分:1)
试试这个:
#include <stdio.h>
int main() {
unsigned long long i1 = 0x0123456789ABCDEFULL;
unsigned long long i2 = 0x11223344AABBCCDDULL;
// window start 7, size 12 bits
// so it should include bits 7..0 from i1 and 63..60 from i2
int windowStart = 7; // bit 7 of i1
int windowSize = 12;
// Number of most significant bits needed from i2
int numBitsFromSecondNum = windowSize - windowStart - 1;
// AND mask of i1 to obtain the least significant bits from it
unsigned long long chunk1 = i1 & ((1 << (windowStart+1)) - 1);
// Right shift i2 to obtain the most significant bits from it
unsigned long long chunk2 = i2 >> (64 - numBitsFromSecondNum);
// Concatenation of the 2 chunks
unsigned long long result = (chunk1 << numBitsFromSecondNum) | chunk2;
printf("%llX\n", chunk1); // prints: EF
printf("%llX\n", chunk2); // prints: 1
printf("%llX\n", result); // prints: EF1
return 0;
}
窗口的开始和大小不在您的问题中,但我选择它们与4位对齐,以便轻松查看以十六进制打印的输出。
在上面的代码中,我假设unsigned long long
(与unsigned long long int
相同)大小为64位。 C标准保证它至少为64位,这意味着它可能更大(例如128位)。最好用(8*sizeof(unsigned long long))
替换。
答案 1 :(得分:0)
这有点过于复杂,但它可以以更长的时间为代价提供更大的灵活性。
功能签名是:
template <typename... Ts_>
std::string see_bit_range(std::size_t p_start, std::size_t p_length, const Ts_&... p_types)
它创建并返回1
和0
s的字符串,而不是显示它。 p_start
是它应该从右边开始的位数(0
将是第一个变量中最重要的位)。 p_length
是要看多少位。之后,您可以根据需要传入尽可能多的不同类型的变量。我没有检查p_start
或p_length
是否太大,或者如果你将零参数传递给它,那么就不要这样做。
取两个变量:unsigned char var1 = 0b00110011, var 2 = 0b11000000;
。调用类似see_bit_range(1, 10, var1, var2)
的函数,结果是字符串&#34; 0110011 110&#34;。
int main()
{
const uint64_t var1 = 0b0110011; //...0110011
const uint64_t var2 = 3ull << 62; //110...
const int start = 57; //How many bits from the left to start at (64 - 7)
const int length = 10; //How many bits to read
std::cout << see_bit_range(start, length, var1, var2); //0110011 110
}
功能代码如下。 get_var_sum
是计算所有对象大小的辅助工具,否则不重要。它可以完全通过使用new
分配的内存而不是像我那样使用本地数组来省略。
#include <string> //string
#include <cstddef> //size_t
#include <climits> //CHAR_BIT
template <typename T_, typename... Ts_>
struct get_var_sum
{
static constexpr std::size_t value = sizeof(T_) + get_var_sum<Ts_...>::value;
};
template <typename T_>
struct get_var_sum<T_>
{
static constexpr std::size_t value = sizeof(T_);
};
template <typename... Ts_>
std::string see_bit_range(std::size_t p_start, std::size_t p_length, const Ts_&... p_types)
{
std::string out; //The string that represents the bits
constexpr std::size_t SIZE_SUM = get_var_sum<Ts_...>::value; //The size of all the types combined
unsigned char buffer[SIZE_SUM]; //A buffer to store the binary values in
constexpr std::size_t ELEMENTS = sizeof...(Ts_); //The number of elements
const unsigned char* ptrs[ELEMENTS]{ reinterpret_cast<const unsigned char*>(&p_types)... }; //Creates an array of pointers to the objects
std::size_t sizes[ELEMENTS]{ sizeof(Ts_)... }; //Creates an array that holds the sizes of the objects
out.reserve(CHAR_BIT * SIZE_SUM); //Be nice and tell the string what to expect
bool small_endian; //If we're on a small endian or big endian machine
unsigned long long test = 1;
small_endian = *reinterpret_cast<unsigned char*>(&test) == 1;
std::size_t x, y, z = 0;
for (x = 0; x < ELEMENTS; ++x) //For each value
{
for (y = 0; y < sizes[x]; ++y) //For each byte in the value
buffer[z++] = ptrs[x][small_endian ? sizes[x] - y - 1 : y]; //Copy the value into the buffer
}
y = 0;
z = 0;
for (x = p_start; x < p_start + p_length; ++x) //For the bit range specified
{
if ((x - y) / CHAR_BIT == sizes[z]) //If we just reached the end of a variable
{
y = x;
++z;
out.push_back(' '); //Put a space in the string
}
out.push_back(((buffer[x / CHAR_BIT] & (1u << (CHAR_BIT - (x % CHAR_BIT) - 1))) > 0) ? '1' : '0'); //Show if the bit is on or not
}
return out;
}