如何从数组中读取单个位?

5
假设我有一个动态分配的数组。
int* array=new int[10]

这是10 * 4 = 40字节或10 * 32 = 320位。我想要读取第30个字节或第242位的第二位。最简单的方法是什么?我知道可以使用array[30]访问第30个字节,但访问单个位有点棘手。


可能 std::bitset 适合您的需求。 - Oleg Svechkarenko
如果您希望进行位访问,请始终确保使用 uint8_t 类型的数据。否则,机器数据大小和字节顺序可能会导致问题。 - edA-qa mort-ora-y
@edA-qa more-ora-y uint16_t等也可以使用。对于大多数用途,unsigned char、unsigned int等也可以使用。字节序不是问题,而且如果使用sizeof(T)*CHAR_BIT进行精心编写,而不是8、16等,则也不是问题。假设程序需要那种程度的可移植性。 - James Kanze
关于字节序的关注是,如果您有一个 int 数组,您可能会给它分配整数,然后按字节访问它。如果您只使用字节,那么您正确地说不重要,但至少使用无符号。 - edA-qa mort-ora-y
实际上,要访问第30个字节,您需要使用array[29]而不是array[30] :) - Armen Tsirunyan
6个回答

6
bool bitset(void const * data, int bitindex) {
  int byte = bitindex / 8;
  int bit = bitindex % 8;
  unsigned char const * u = (unsigned char const *) data;
  return (u[byte] & (1<<bit)) != 0;
}

这不是基于Jake所描述的数组。 - Benoit Thiery
@Benoit:当然没问题,如果他将数组传递给这个函数,它会正常工作。上述情况失败的唯一情况是有些机器的字节宽度不是8位。 - Erik
在C++中,<cstdint>定义了uint8_t。 - edA-qa mort-ora-y
@edA:那是TR1——它不是一个标准。但它将会在C++0x中出现。 - Erik
@Erik:是的,那就是我想表达的意思) - Armen Tsirunyan
显示剩余5条评论

1

这个正常工作!

#define GET_BIT(p, n) ((((unsigned char *)p)[n/8] >> (n%8)) & 0x01)

int main()
{
    int myArray[2] = { 0xaaaaaaaa, 0x00ff00ff };
    for( int i =0 ; i < 2*32 ; i++ )
        printf("%d", GET_BIT(myArray, i));
    return 0;
}

输出:

0101010101010101010101010101010111111111000000001111111100000000

小心字节序!


1

首先,如果你正在进行位运算,通常最好将元素设置为无符号整数类型(尽管在这种情况下,它并没有太大的区别)。至于访问位:要访问n个int数组中的第i位:

static int const bitsPerWord = sizeof(int) * CHAR_BIT;
assert( i >= 0 && i < n * bitsPerWord );
int wordIndex = i / bitsPerWord;
int bitIndex = i % bitsPerWord;

然后阅读:

return (array[wordIndex] & (1 << bitIndex)) != 0;

设定:

array[wordIndex] |= 1 << bitIndex;

并进行重置:

array[wordIndex] &= ~(1 << bitIndex);

或者你可以使用bitset,如果n是常量,或者使用vector<bool>boost::dynamic_bitset,如果它不是常量,并让其他人来完成这项工作。


0
你可以使用类似这样的代码:
!((array[30] & 2) == 0)

array[30] 是整数。

& 2 是按位与运算,用于屏蔽第二位(2 = 00000010)。

== 0 将检查掩码结果是否为0。

! 将否定该结果,因为我们正在检查它是否为1而不是零....


0

这里需要位运算...

if(array[5] & 0x1)
{
//the first bit in array[5] is 1
}
else
{
//the first bit is 0
}

if(array[5] & 0x8)
{
//the 4th bit in array[5] is 1
}
else
{
//the 4th bit is 0
}

0x8在二进制中是00001000。进行按位与操作可以屏蔽所有其他位,并允许您查看该位是1还是0。

int通常为32位,因此您需要进行一些算术运算才能获取整个数组中的某个特定位数。


0

根据下面的评论进行编辑 - 数组包含32位整数,而不是8位uchar。

int pos = 241; // I start at index 0
bool bit242 = (array[pos/32] >> (pos%32)) & 1;

2
他的数组是int类型,而不是char/unsigned char类型,因此您不能使用/8%8 - Erik
或者CHAR_BIT是8:-)。但是除法是在pos上进行的;对值的断言应该先于代码,否则负数不是唯一的问题。 - James Kanze

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接