我有一个表示8x8“bit”块的数组
unsigned char plane[8]
我想要做的是水平循环这个“位”块
并计算发生变化的次数
1
和0
。
当我提取一点时,它被存储在一个 unsigned char,所以基本上我想增加一个计数 当一个char非零而另一个为零时。
我所拥有的是以下内容:
int getComplexity(unsigned char *plane) {
int x, y, count = 0;
unsigned char bit;
for(x = 0; x < 8; x++) {
for(y = 0; y < 8; y++) {
if(y == 0) {
bit = plane[x] & 1 << y;
continue;
}
/*
MISSING CODE
*/
}
}
}
对于丢失的代码,我可以这样做:
if( (bit && !(plane[x] & 1 << y)) || (!bit && (plane[x] & 1 << y)) ) {
bit = plane[x] & 1 << y;
count++;
}
然而,我真正想要的是,如果有的话 巧妙的按位操作来代替这一步 有两个单独的测试。
答案 0 :(得分:2)
这实际上只是一个gcc解决方案,因为popcnt内在函数不能用于每个其他编译器。
unsigned char plane[8];
static const uint64_t tmask = 0x8080808080808080UL;
uint64_t uplane = *(uint64_t *)plane; // pull the whole array into a single uint
return __builtin_popcnt( ~tmask & (uplane ^ (uplane >> 1) ) );
对于x86,popcnt指令实际上没有实现,直到sse4.2(所以最近)。 此外,尽管看起来它依赖于字节序,但它并不是因为掩码所允许的单个字节都不允许交互。 它对内存的工作方式做了一些假设:\
作为旁注在&#34;水平&#34;中做同样的事情。方向也很简单:
return __builtin_popcnt(0xFFFFFFFFFFFFFFUL & ( uplane ^ (uplane >> 8) ) );