Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 扫描位阵列以获得多个位的模式_C++_C++11_Memory Management_Bit Manipulation_Dynamic Allocation - Fatal编程技术网

C++ 扫描位阵列以获得多个位的模式

C++ 扫描位阵列以获得多个位的模式,c++,c++11,memory-management,bit-manipulation,dynamic-allocation,C++,C++11,Memory Management,Bit Manipulation,Dynamic Allocation,我正在编写一个内存分配器,它由一个位图(数组ofuint8\t)支持。当前,当出现分配请求时,我按从0到n位的顺序扫描位图,并搜索一个可以满足请求的空间。(位1表示使用了一个0表示的页面是空闲的)现在不是一次一位搜索一个空间,有没有技术可以更快地扫描整个阵列?i、 e如果3页内存的请求到达,我想一次搜索数组中的000模式,理想情况下没有循环 PS:我没有使用std::bitset,因为它不适用于我正在使用的编译器。AFAIK不允许我也搜索多个位 编辑:位被压缩到字节中。一个uint8\u t有8

我正在编写一个内存分配器,它由一个位图(数组of
uint8\t
)支持。当前,当出现分配请求时,我按从0到n位的顺序扫描位图,并搜索一个可以满足请求的空间。(位1表示使用了一个0表示的页面是空闲的)现在不是一次一位搜索一个空间,有没有技术可以更快地扫描整个阵列?i、 e如果3页内存的请求到达,我想一次搜索数组中的
000
模式,理想情况下没有循环

PS:我没有使用
std::bitset
,因为它不适用于我正在使用的编译器。AFAIK不允许我也搜索多个位


编辑:位被压缩到字节中。一个
uint8\u t
有8页(每位1页)编码在其中。

要扫描一个空页,您可以在位数组中循环一个完整的字节,并检查它是否小于255。如果较小,则至少有一个零位。更好的方法是一次扫描32或64位(无符号整数),然后缩小uint内的搜索范围

要优化一个位,可以使用零位跟踪第一个字节(并在释放页面时更新该位置)。一旦分配了空闲页面,这可能会给出一个误报,但至少下次扫描可以从那里开始,而不是从开始

如果您愿意以2的幂(取决于您的数据结构)对齐较大的块,则可以优化对多个页面的扫描。例如,要分配8个页面,您只需扫描一个为零的完整字节:

1 page: scan for any zero bit (up to 64 bits at a time)
2 pages: scan for 2 zero bits at bit position 0,2,4,6
3-4 pages: scan for zero nibble (for 3 pages, the fourth would be available for 1 page then)
5-8 pages: scan for an empty byte

for each of the above, you could first scan 64 bits at a time.
这样,您就不必担心(或检查)字节/uint32/uint64边界处的零范围重叠


对于每种类型,都可以保留/更新带有第一个自由块的起始位置。

我想这不是对您问题的完整回答,但我希望以下功能可以有所帮助

template <typename I>
bool scan_n_zeros (I iVal, std::size_t num)
 {
   while ( --num )
      iVal |= ((iVal << 1) | I{1});

   return iVal != I(-1);
 }

这是否会形成uint16,以便我可以将两个字节分组到uint16中,以说明从一个字节到下一个字节的转换,然后将窗口从开始到结束滑动一个字节?@HamzaYerlikaya-我开发了一个模板函数,正是因为它适用于所有整数无符号类型。您能稍微扩展一下位移位的工作原理吗。
#include <iostream>

template <typename I>
bool scan_n_zeros (I iVal, std::size_t num)
 {
   while ( --num )
      iVal |= ((iVal << 1) | I{1});

   return iVal != I(-1);
 }

int main()
 {
   uint8_t  u0 { 0b00100100 };
   uint8_t  u1 { 0b00001111 };
   uint8_t  u2 { 0b10000111 };
   uint8_t  u3 { 0b11000011 };
   uint8_t  u4 { 0b11100001 };
   uint8_t  u5 { 0b11110000 };

   std::cout << scan_n_zeros(u0, 2U) << std::endl; // print 1
   std::cout << scan_n_zeros(u0, 3U) << std::endl; // print 0
   std::cout << scan_n_zeros(u1, 4U) << std::endl; // print 1
   std::cout << scan_n_zeros(u1, 5U) << std::endl; // print 0
   std::cout << scan_n_zeros(u2, 4U) << std::endl; // print 1
   std::cout << scan_n_zeros(u2, 5U) << std::endl; // print 0
   std::cout << scan_n_zeros(u3, 4U) << std::endl; // print 1
   std::cout << scan_n_zeros(u3, 5U) << std::endl; // print 0
   std::cout << scan_n_zeros(u4, 4U) << std::endl; // print 1
   std::cout << scan_n_zeros(u4, 5U) << std::endl; // print 0
   std::cout << scan_n_zeros(u5, 4U) << std::endl; // print 1
   std::cout << scan_n_zeros(u5, 5U) << std::endl; // print 0
 }