一个宏来计算打开的位(设置)

时间:2014-02-18 19:05:29

标签: c bit-manipulation bit-shift

我的任务是编写一个宏来检查INT数组中有多少元素已经激活了5位。

我知道宏是一种非常冒险的方式,但这是一些考试中出现的问题。

这是我的代码:

#include <stdio.h>
#define RESULT 5
#define SIZE 8
#define BITW(arr, length, counter)\
    int mask=0b00000001, bits=0, i=0, j=0;\
    for (i=0; i<length; i++){\
        for (j=0; j<sizeof(arr[i])*SIZE; j++){\
            if(mask&arr[i]>>j)\
                bits++;\
        }\
        if (bits==RESULT)\
            counter++;\
    }
int main(void){
    int arr[4]={0b11111000,0b11100011,0b11001100,0b11000000};
    int res=0; int counter=0;
    BITW(arr, 4, counter);
    printf("%d",counter);


}

宏的问题是我无法调试我的代码。我去了几次没有成功,但我意识到我得到的结果是1而不是2。

计数器变量是计算有多少元素有5位的计数器变量。位变量在某个元素中计算有多少位。

感谢您的帮助。

4 个答案:

答案 0 :(得分:7)

如果你真的想要一个宏,我可能会做这样的事情:

static const int bits_per_nibble[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
#define BITS_PER_U8(x) (bits_per_nibble[(x) & 0xf] + bits_per_nibble[((x) >> 4) & 0xf])
#define BITS_PER_U16(x) (BITS_PER_U8((x) & 0xff) + BITS_PER_U8(((x) >> 8) & 0xff))
#define BITS_PER_U32(x) (BITS_PER_U16((x) & 0xffff) + BITS_PER_U16(((x) >> 16) & 0xffff))

如果需要,定义BITS_PER_U64应该是一个明显的扩展。

然而,将其作为一个小型内联函数来做会更安全,更好的解决方案......

还有this,其中有关于如何以各种方式获得“人口数量”的整个部分......

答案 1 :(得分:2)

在计算每个数组元素中的位之前,宏无法将bits设置为零。它仅在整个数组上的循环之前将bits设置为零。

答案 2 :(得分:1)

我说

if(mask&arr[i]>>j)\
    bits++;\
     

是错误的,因为它测试结果中是否设置了任何位,而不是全部   他们是设定的。我重写代码来计算1中的位数   字节到

bits=0;
for (mask=0b10000000; mask!=0; mask=mask>>1)
    if (arr[i]&mask)
        bits++;
if (bits==5)
    ...
     

注意这仅适用于掩码是无符号或超过8位的情况,因此char不会>做(你的int是好的)。

但这是错误的。

然而,

#define BITW(arr, length, counter)\
int mask=0b00000001, bits=0, i=0, j=0;\
for (i=0; i<length; i++){\
    bits=0;                         //<---- This line is missing from your code
    for (j=0; j<sizeof(arr[i])*SIZE; j++){\
        if(mask&arr[i]>>j)\
            bits++;\
    }\
    if (bits==RESULT)\
        counter++;\
}

不会为每个字节重置位计数器。

要调试宏,首先编写一个可以调试的函数;然后,当你确定它有效时,将函数转换为宏。

答案 3 :(得分:0)

Eric回答了主要问题。

  

宏的问题在于我无法调试我的代码。

您可以在宏中使用printf,或者您可以将宏调用替换为宏中的代码段。