我最近从一本教科书中完成了一些位操作练习,并掌握了一些坚定操作位的核心思想。我发表这篇文章的主要问题是优化我当前的代码。我预感到有些功能可以让我更好地接近。您对以下代码有什么建议吗?
#include <stdio.h>
#include "funcs.h"
// basically sizeof(int) using bit manipulation
unsigned int int_size(){
int size = 0;
for(unsigned int i = ~00u; i > 0; i >>= 1, size++);
return size;
}
// get a bit at a specific nth index
// index starts with 0 on the most significant bit
unsigned int bit_get(unsigned int data, unsigned int n){
return (data >> (int_size() - n - 1)) & 1;
}
// set a bit at a specific nth index
// index starts with 0 on the most significant bit
unsigned int bit_set(unsigned int data, unsigned int n){
return data | (1 << (int_size() - n - 1));
}
// gets the bit width of the data (<32)
unsigned int bit_width(unsigned int data){
int width = int_size();
for(; width > 0; width--)
if((data & (1 << width)) != 0)
break;
return width + 1;
}
// print the data contained in an unsigned int
void print_data(unsigned int data){
printf("%016X = ",data);
for(int i = 0; i < int_size(); i++)
printf("%X",bit_get(data,i));
putchar('\n');
}
// search for pattern in source (where pattern is n wide)
unsigned int bitpat_search(unsigned int source, unsigned int pattern,
unsigned int n){
int right = int_size() - n;
unsigned int mask = 0;
for(int i = 0; i < n; i++)
mask |= 1 << i;
for(int i = 0; i < right; i++)
if(((source & (mask << (right - i))) >> (right - i) ^ pattern) == 0)
return i - bit_width(source);
return -1;
}
// extract {count} bits from data starting at {start}
unsigned int bitpat_get(unsigned int data, int start, int count){
if(start < 0 || count < 0 || int_size() <= start || int_size() <= count || bit_width(data) != count)
return -1;
unsigned int mask = 1;
for(int i = 0; i < count; i++)
mask |= 1 << i;
mask <<= int_size() - start - count;
return (data & mask) >> (int_size() - start - count);
}
// set {count} bits (basically width of {replace}) in {*data} starting at {start}
void bitpat_set(unsigned int *data, unsigned int replace, int start, int count){
if(start < 0 || count < 0 || int_size() <= start || int_size() <= count || bit_width(replace) != count)
return;
unsigned int mask = 1;
for(int i = 0; i < count; i++)
mask |= 1 << i;
*data = ((*data | (mask << (int_size() - start - count))) & ~(mask << (int_size() - start - count))) | (replace << (int_size() - start - count));
}
答案 0 :(得分:1)
因为你的int_size()函数每次都可以节省一些时间返回相同的值:
unsigned int int_size(){
static unsigned int size = 0;
if (size == 0)
for(unsigned int i = ~00u; i > 0; i >>= 1, size++);
return size;
}
所以它只计算一次值。
但是用sizeof(int)*8
替换所有这个函数的调用会好得多。
答案 1 :(得分:0)
我查看了你的代码,没有任何东西可以跳出来。
总的来说,不要为小东西出汗。如果代码运行并正常工作,不用担心。如果您真的关心性能,请继续通过分析器运行代码。
总的来说,我会说你可能要处理的一件事就是&#34;偏执狂&#34;我在你的代码中看到了int的宽度。我通常在stdint.h中使用固定长度类型,并给调用者一些关于他们想要处理的int的长度(即uint8_t,uint16_t,uint32_t等)的选项。
此外,在C99中,还有一些位域,允许将每个位寻址。
答案 2 :(得分:0)
unsigned int int_size(){
return __builtin_popcount((unsigned int) -1) / __builtin_popcount((unsigned char) -1);
}
这应该比循环更快。
答案 3 :(得分:-1)
在所有其他方面包含int_size()似乎会破坏性能,除非编译器真的善于优化该循环。
您可以使用uint32_t而不是int,然后您可以预先了解大小。
您还可以使用sizeof(int)来获取int的字节大小并乘以8.我还没有看到一个将字节定义为8位以外的环境,但标准看起来似乎允许它说它是实现定义。