С++ использует массив символов для базового хранения битов/не может заставить работать побитовые операции

Итак, у меня есть массив беззнаковых символов, в настоящее время я пытаюсь написать метод Set (меняет бит в данном индексе на 1). Лучший способ, который я мог придумать, - вместо создания маски для всего массива, я бы просто создал маску размером с байт и только замаскировал место индекса в массиве с заданным битом, который пользователь хочет изменить . Однако каждый раз, когда я пытаюсь это сделать, либо ничего не происходит с результирующим массивом после ИЛИ с маской всех 0 с 1 в битовом индексе, либо я получаю ошибку сегмента. Лучшее, что мне удалось сделать, это изменить правильный бит в первом индексе массива. Как сейчас настроен мой код, я понимаю, почему он меняет только правильный бит в первом байте массива, но каждая попытка изменить это не удалась, я не думаю, что это должно быть сложно, я просто чувствую, что я Я что-то упускаю, но страницы чтения и поиски в гугле ни к чему меня не привели. Вот фрагмент моего кода на данный момент...

void BitArray::Set (unsigned int index)
 70 {
 71     int spot;       // index in barray where 
 72                     // bit to be set is located
 73     char mask;       
 74     if (index < 8)
 75     {   
 76         spot = 0;
 77         mask = 1 >> index - 1;
 78     }   
 79     else
 80     {
 81         int spot = index / 8;
 82         mask = 1 << (index - (8*spot) - 1);
 83     }   
 84     
 85     *barray = *barray | mask;
 86 }   

Вместо *barray = *barray | mask, я бы интуитивно хотел что-то вроде barray[spot] = barray[spot] | маска; работать. Любая помощь приветствуется.


person user1079357    schedule 03.12.2011    source источник
comment
По какой причине вы не используете vector<bool> или bitset?   -  person Bill    schedule 04.12.2011
comment
Во-первых, если вы используете побитовые операторы, вы почти наверняка должны использовать беззнаковые типы.   -  person Keith Thompson    schedule 04.12.2011
comment
@KeithThompson, побитовые операции игнорируют знак   -  person Abyx    schedule 04.12.2011
comment
@Abyx: не обязательно. Например, сдвиг отрицательного значения либо определяется реализацией, либо не определен.   -  person Keith Thompson    schedule 04.12.2011
comment
@KeithThompson, сдвиг не является побитовой операцией.   -  person Abyx    schedule 04.12.2011
comment
@Abyx: N1256 6.5p4 говорит, Некоторые операторы (унарный оператор ~ и бинарные операторы <<, >>, &, ^ и |, вместе описываемые как побитовые операторы) должны иметь операнды целочисленного типа. Эти операторы возвращают значения, которые зависят от внутренних представлений целых чисел и имеют аспекты, определяемые реализацией, и неопределенные аспекты для подписанных типов. Некоторые операции над знаковыми типами хорошо определены, но мне гораздо проще просто использовать беззнаковый тип, чем помнить, какие случаи безопасны.   -  person Keith Thompson    schedule 04.12.2011


Ответы (2)


Я не понимаю, почему вы идете против своего интуитивного понимания array[spot] = barray[spot] | mask; И, кажется, вы усложняете расчеты пятна и маски, чем это необходимо.

Почему вы сделали index < 8 особым случаем?

if(index < 8) 
    spot = 0;
...
else
    spot = index / 8;

В обоих случаях index / 8 дает вам правильный индекс байта, верно?

Во-вторых, как любая из следующих строк дает вам правильную битовую позицию? Почему ты вообще переключаешься вправо? Какое отношение имеет индекс байта, к которому у вас есть доступ, к положению бита в байте?

mask = 1 >> index - 1;

mask = 1 << (index - (8*spot) - 1);

Вот мое непроверенное решение:

void BitArray::Set(unsigned int index)
{
    int spot = index / 8;
    char bit = 1 << (index % 8);
    barray[spot] = barray[spot] | bit;
}
person bames53    schedule 03.12.2011

Может проблема в barray?
В любом случае, этот код должен работать:

void BitArray::Set (unsigned int index)
{
    //assert(index / 8 < arraySize);

    static const unsigned char masks[8] = {1, 2, 4, 8, 16, 32, 64, 128};

    barray[index / 8] |= masks[index % 8];
}

Обратите внимание, что любой современный компилятор создаст код, равный

barray[index >> 3] |= masks[index & 7];
person Abyx    schedule 03.12.2011