Как сдвинуть указатель на несколько бит?
От: Аноним  
Дата: 16.10.06 06:35
Оценка: :))) :))) :)))
Есть массив элементов типа unsigned long int DI[100]; есть указатель на начало массива unsigned char *ptr; можно ли сдвинуть указатель на несколько битов вперед относительно начала массива, так чтобы он указывал допустим на 3-й бит первого элемента массива? и как это реализовать? Заранее спасибо.
Re: Как сдвинуть указатель на несколько бит?
От: Bell Россия  
Дата: 16.10.06 06:38
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть массив элементов типа unsigned long int DI[100]; есть указатель на начало массива unsigned char *ptr; можно ли сдвинуть указатель на несколько битов вперед относительно начала массива, так чтобы он указывал допустим на 3-й бит первого элемента массива? и как это реализовать? Заранее спасибо.


Нет. Минимальная адресуемая сущность — это байт.
А зачем нужно?
Любите книгу — источник знаний (с) М.Горький
Re[2]: Как сдвинуть указатель на несколько бит?
От: Аноним  
Дата: 16.10.06 06:43
Оценка:
Мне надо найти в массиве DI запрашиваемый бит и шагать побайтно, потом с полученными данными дальше работать. Мне надо реализовать вторую функцию Modbus.
Re: Как сдвинуть указатель на несколько бит?
От: Аноним  
Дата: 16.10.06 06:48
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть массив элементов типа unsigned long int DI[100]; есть указатель на начало массива unsigned char *ptr; можно ли сдвинуть указатель на несколько битов вперед относительно начала массива, так чтобы он указывал допустим на 3-й бит первого элемента массива? и как это реализовать? Заранее спасибо.


Для этого достаточно обычных указателей и побитовых операций.
Указателей не "биты" не существует.
Re[3]: Как сдвинуть указатель на несколько бит?
От: denaturat  
Дата: 16.10.06 06:49
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Мне надо найти в массиве DI запрашиваемый бит и шагать побайтно, потом с полученными данными дальше работать. Мне надо реализовать вторую функцию Modbus.


Найди этот бит, а потом передвинь все элементы так, чтобы получился нормальный массив, в котором и будет ptr++;
Re[4]: Как сдвинуть указатель на несколько бит?
От: Аноним  
Дата: 16.10.06 06:55
Оценка:
Как передвинуть, используя операции сдвига? можно подробней7
Re[4]: Как сдвинуть указатель на несколько бит?
От: Voin_Di  
Дата: 16.10.06 07:14
Оценка: :)
Спасибо, поняла как сделать
Re[5]: Как сдвинуть указатель на несколько бит?
От: np9mi7 Россия  
Дата: 16.10.06 07:16
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Как передвинуть, используя операции сдвига? можно подробней7


Можно ms-help://MS.MSDN.vAug06.en/script56/html/js56jsoprrshift.htm
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Re[3]: Как сдвинуть указатель на несколько бит?
От: Кодт Россия  
Дата: 16.10.06 07:51
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Мне надо найти в массиве DI запрашиваемый бит и шагать побайтно, потом с полученными данными дальше работать. Мне надо реализовать вторую функцию Modbus.


Напиши адаптер. Степень адаптации может варьироваться — начиная от просто побайтового чтения
class ShiftedStream
{
    BYTE const* data;
    int length;
    int bytePos, bitPos;
    
    BYTE leadBits() const { return bytePos<=0 || bytePos>length ? 0 : data[bytePos]>>bitPos; }
    BYTE tailBits() const { return bytePos<0 || bytePos>=length ? 0 : data[bytePos+1]<<(8-bitPos); }
public:
    BYTE peek() const { return leadBits() | tailBits(); }
    BYTE read() { BYTE b = peek(); ++bytePos; }
};

и кончая итератором произвольного доступа к неконстантному массиву.
Код итератора выглядит громоздко, поэтому без нужды расписывать не буду.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re: Пжалста :)
От: remark Россия http://www.1024cores.net/
Дата: 16.10.06 13:27
Оценка: :))) :))) :))) :))) :))) :)))
Здравствуйте, Аноним, Вы писали:

А>Есть массив элементов типа unsigned long int DI[100]; есть указатель на начало массива unsigned char *ptr; можно ли сдвинуть указатель на несколько битов вперед относительно начала массива, так чтобы он указывал допустим на 3-й бит первого элемента массива? и как это реализовать? Заранее спасибо.


p = p + 0.25;





1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Как сдвинуть указатель на несколько бит?
От: sraider http://dvinogradov.blogspot.com
Дата: 16.10.06 13:39
Оценка:
А>>Есть массив элементов типа unsigned long int DI[100]; есть указатель на начало массива unsigned char *ptr; можно ли сдвинуть указатель на несколько битов вперед относительно начала массива, так чтобы он указывал допустим на 3-й бит первого элемента массива? и как это реализовать? Заранее спасибо.

А>Для этого достаточно обычных указателей и побитовых операций.

А>Указателей не "биты" не существует.

Пару строк кода:
struct BitPointer
{
   char* address;
   char bitnumber;
};

и они существуют
Re[2]: Пжалста :)
От: Voin_Di  
Дата: 16.10.06 14:23
Оценка: :))
Здравствуйте, remark

Сделала, как вы посоветовали. Пишет
Illegal floating point;
Что делать?
Re[3]: Как сдвинуть указатель на несколько бит?
От: Аноним  
Дата: 16.10.06 14:28
Оценка:
Здравствуйте, sraider, Вы писали:

S>Пару строк кода:

S>
S>struct BitPointer
S>{
S>   char* address;
S>   char bitnumber;
S>};
S>

S>и они существуют

Ну тогда надо вспомнить и про std::bitset
Способов решения проблемы автора топика — вагон и маленькая тележка...
Re[3]: Пжалста :)
От: Анатолий Широков СССР  
Дата: 16.10.06 14:31
Оценка:
Здравствуйте, Voin_Di, Вы писали:

V_D>Здравствуйте, remark


V_D>Сделала, как вы посоветовали. Пишет

V_D>Illegal floating point;
V_D>Что делать?

А Вы серьезно или вторите автору? Я что-то уже засомневался.
Re[2]: Пжалста :)
От: Voin_Di  
Дата: 16.10.06 15:47
Оценка:
Здравствуйте, remark,
Компилятор ругается на недопустимость опарации с указателем
Re[4]: Пжалста :)
От: Voin_Di  
Дата: 16.10.06 15:50
Оценка:
Здравствуйте, Анатолий Широков, нет, просто свой ник вспомнила
Re[3]: Пжалста :)
От: remark Россия http://www.1024cores.net/
Дата: 16.10.06 16:35
Оценка:
Здравствуйте, Voin_Di, Вы писали:

V_D>Здравствуйте, remark,

V_D> Компилятор ругается на недопустимость опарации с указателем

Это была шутка


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Пжалста :)
От: night beast СССР  
Дата: 16.10.06 18:30
Оценка: 7 (1) :))
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Аноним, Вы писали:


А>>Есть массив элементов типа unsigned long int DI[100]; есть указатель на начало массива unsigned char *ptr; можно ли сдвинуть указатель на несколько битов вперед относительно начала массива, так чтобы он указывал допустим на 3-й бит первого элемента массива? и как это реализовать? Заранее спасибо.


Зачем интересно такое понадобилось? По-любому лаба.

R>
R>p = p + 0.25;
R>


R>



как не стыдно над новичками издеваться

собственно, чтобы сгладить первое впечатление набросок
#include <iostream>
#include <limits>
#include <iterator>
#include <bitset>

template< int shift = 0 >
struct shift_iterator
{
    typedef std::random_access_iterator_tag iterator_category;
    typedef unsigned long value_type;
    struct reference;
    typedef ptrdiff_t difference_type;

    value_type * ptr;

    shift_iterator ( value_type * src ) : ptr (src) {}

    reference operator * () const { return reference (this->ptr); }
    reference operator [] (difference_type) const;

    template<typename T>
    struct temporary {
        T value;
        explicit temporary ( T src ) : value (src) {}

        T * operator -> () { return & this->value; }
    };
    temporary<reference> operator -> () const { return temporary<reference> ( reference (this->ptr) ); }


    shift_iterator & operator ++ () { ++this->ptr; return (*this); }
    shift_iterator & operator -- () { --this->ptr; return (*this); }

    shift_iterator operator ++ (int) { shift_iterator tmp (*this); ++(*this); return tmp; }
    shift_iterator operator -- (int) { shift_iterator tmp (*this); --(*this); return tmp; }

    shift_iterator & operator += ( difference_type n ) { this->ptr += n; return (*this); }
    shift_iterator & operator -= ( difference_type n ) { this->ptr -= n; return (*this); }
};

template< int shift >
struct shift_iterator<shift>::reference {
    static const int digits = std::numeric_limits<value_type>::digits;
    typedef std::bitset<digits> bitset;


    value_type * ptr;
    reference ( value_type * src ) : ptr (src) {}
    value_type value () const { 

        std::cout << __FUNCTION__ << std::endl;

        bitset tmp (*this->ptr); // берем текущий элемент.
        std::cout << tmp.to_ulong () << ":" << tmp << std::endl;
        bitset val = tmp >> shift; // удаляем хвост предынущего элемента. теперь val хранит младшую часть значения.
        std::cout << val.to_ulong () << ":" << val << std::endl;

        tmp = *(this->ptr+1); // берем следующий элемент.
        std::cout << tmp.to_ulong () << ":" << tmp << std::endl;
        tmp = (tmp << digits-shift); // получаем старшую чась значения.
        std::cout << tmp.to_ulong () << ":" << tmp << std::endl;
        val |= tmp; // склеиваем младшую и старшую части.
        std::cout << val.to_ulong () << ":" << val << std::endl;

        return val.to_ulong ();  // возвращаем значение.
    }

    operator value_type () const { return this->value (); }

    reference & operator = ( value_type value ) { 
        static bitset const mask = bitset ().set(); // все единицы
        static bitset const hmask= mask << shift; // старшая часть = единицы
        static bitset const lmask= ~ hmask; // младшая часть = единицы

        std::cout << __FUNCTION__ << std::endl;

        std::cout << lmask << std::endl;
        std::cout << hmask << std::endl;

        bitset tmp (*this->ptr); // берем текущий элемент.
        bitset val (value); // и новое значение.

        std::cout << tmp.to_ulong () << ":" << tmp << std::endl;
        std::cout << val.to_ulong () << ":" << val << std::endl;
        val = ( val << shift ) | ( val >> digits-shift ); // для удобства сдвигаем циклически новое значение на число бит.
        std::cout << val << std::endl;
        tmp = ( tmp & lmask ) | ( val & hmask ); // склеиваем хвост предыдущего элемента и младшую часть нового значения.
        std::cout << tmp << std::endl;
        *this->ptr = tmp.to_ulong (); // записываем в текущий элемент это значение.

        tmp = *(this->ptr+1); // берем следующий элемент.
        std::cout << tmp.to_ulong () << ":" << tmp << std::endl;
        tmp = ( val & lmask ) | ( tmp & hmask ); // склеиваем старшую часть нового значения и начало следующего элемента.
        std::cout << tmp << std::endl;
        *(this->ptr+1) = tmp.to_ulong (); // записываем полученное значение в массив.

        return (*this); 
    }

};

int main() { 
    unsigned long x[4] = {7,5,3,5};
    shift_iterator<2> it (x);
    std::cout << it->value () << std::endl;
    *it = std::numeric_limits<unsigned long>::max()-4;

    return 0;
}



Предупреждаю сразу.
У итератора не хватает операций +,-, и операций сравнения. Добавить не сложно много но ручной работы.
bitset применял для наглядности. поэтому его лучше заменить непосредственно на value_type.

Кто до сюда дочитал, критикуйте
Re: Как сдвинуть указатель на несколько бит?
От: superlexx  
Дата: 16.10.06 19:47
Оценка: :)
используйте IEC 61131-3 IL (instruction list), там есть побитная регистровая адресация (3 LSBs адреса — бит адресируемого байта)
Re: Как сдвинуть указатель на несколько бит?
От: Ux  
Дата: 17.10.06 05:38
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть массив элементов типа unsigned long int DI[100]; есть указатель на начало массива unsigned char *ptr; можно ...


Для реализации МодБас необязательно хранить ячейки в упакованном виде, хотя у меня кеш так и реализован, а можно в виде массива 32-х битных интежеров. Заодно получите возможность хранить неопределённые состояния.
Re[3]: Пжалста :)
От: remark Россия http://www.1024cores.net/
Дата: 17.10.06 06:40
Оценка: 6 (1)
Здравствуйте, night beast, Вы писали:

NB>собственно, чтобы сгладить первое впечатление набросок

NB>Кто до сюда дочитал, критикуйте

Слишком много кода

См. здесь

template<class Base, int ShiftBits, class CharType = boost::iterator_value<Base>::type>
class shift_iter : 
    public boost::iterator_adaptor<
        shift_iter<Base, ShiftBits, CharType>,
        Base, CharType, boost::single_pass_traversal_tag, CharType>
{
public:
    template<class T>
        shift_iter(T start) 
        : boost::iterator_adaptor<shift_iter<Base, ShiftBits, CharType>,
        Base, CharType, boost::single_pass_traversal_tag, CharType>
        (Base(start))
        , m_first(true)
    {}

private:
    CharType dereference() const 
    {
        if (m_first)
        {
            m_buffer = *const_cast<shift_iter*>(this)->base_reference();
            ++(const_cast<shift_iter*>(this)->base_reference());
            m_first = false;
        }

        m_last_buffer = m_buffer;
        m_buffer = *const_cast<shift_iter*>(this)->base_reference();

        CharType retval = m_last_buffer << ShiftBits;
        retval += (unsigned)m_buffer >> (sizeof(base_value_type)*8-ShiftBits);
        return retval;
    }

    typedef typename boost::iterator_value<Base>::type base_value_type;
    mutable base_value_type m_buffer;
    mutable base_value_type m_last_buffer;
    mutable bool m_first;
    friend class boost::iterator_core_access;
};



Тестируем:

Проходим по последовательности байтов с шагом по 4 бита и со сдвигом на 3 бита:

void test()
{
    byte data[] = {0x79, 0xe3, 0x11, 0xa5};

    {
        const byte* first = data;
        const byte* const last = data + sizeof(data)/sizeof(*data);
        for (; first != last; ++first)
            std::cout << to_hex(*first).c_str() << " ";
        std::cout << std::endl;
    }

    {
        typedef boost::archive::iterators::transform_width<
            shift_iter<byte*, 3>, 4, 8> my_iter;

        my_iter first (data);
        my_iter last (data + sizeof(data)/sizeof(*data));

        for (; first != last; ++first)
            std::cout << to_hex(*first).c_str() << " ";
        std::cout << std::endl;
    }
}



Вывод:

79 E3 11 A5
0C 0F 01 08 08 0D



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Пжалста :)
От: e-garin Россия  
Дата: 17.10.06 07:17
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, night beast, Вы писали:


NB>>собственно, чтобы сгладить первое впечатление набросок

NB>>Кто до сюда дочитал, критикуйте

R>Слишком много кода


R>См. здесь


R>
R>template<class Base, int ShiftBits, class CharType = boost::iterator_value<Base>::type>
R>class shift_iter : 
R>    public boost::iterator_adaptor<
R>        shift_iter<Base, ShiftBits, CharType>,
R>        Base, CharType, boost::single_pass_traversal_tag, CharType>
R>{
R>public:
R>    template<class T>
R>        shift_iter(T start) 
R>        : boost::iterator_adaptor<shift_iter<Base, ShiftBits, CharType>,
R>        Base, CharType, boost::single_pass_traversal_tag, CharType>
R>        (Base(start))
R>        , m_first(true)
R>    {}

R>private:
R>    CharType dereference() const 
R>    {
R>        if (m_first)
R>        {
R>            m_buffer = *const_cast<shift_iter*>(this)->base_reference();
R>            ++(const_cast<shift_iter*>(this)->base_reference());
R>            m_first = false;
R>        }

R>        m_last_buffer = m_buffer;
R>        m_buffer = *const_cast<shift_iter*>(this)->base_reference();

R>        CharType retval = m_last_buffer << ShiftBits;
R>        retval += (unsigned)m_buffer >> (sizeof(base_value_type)*8-ShiftBits);
R>        return retval;
R>    }

R>    typedef typename boost::iterator_value<Base>::type base_value_type;
R>    mutable base_value_type m_buffer;
R>    mutable base_value_type m_last_buffer;
R>    mutable bool m_first;
R>    friend class boost::iterator_core_access;
R>};
R>



R>Тестируем:


R>Проходим по последовательности байтов с шагом по 4 бита и со сдвигом на 3 бита:


R>
R>void test()
R>{
R>    byte data[] = {0x79, 0xe3, 0x11, 0xa5};

R>    {
R>        const byte* first = data;
R>        const byte* const last = data + sizeof(data)/sizeof(*data);
R>        for (; first != last; ++first)
R>            std::cout << to_hex(*first).c_str() << " ";
R>        std::cout << std::endl;
R>    }

R>    {
R>        typedef boost::archive::iterators::transform_width<
R>            shift_iter<byte*, 3>, 4, 8> my_iter;

R>        my_iter first (data);
R>        my_iter last (data + sizeof(data)/sizeof(*data));

R>        for (; first != last; ++first)
R>            std::cout << to_hex(*first).c_str() << " ";
R>        std::cout << std::endl;
R>    }
R>}
R>


Мне кажется для новичка — крутовато... А уж для лабы и подавно. Препод поперхнётся, бедненький.
А мне нравится
А мне нравится жить :).
Re[4]: Пжалста :)
От: night beast СССР  
Дата: 17.10.06 09:37
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, night beast, Вы писали:


NB>>собственно, чтобы сгладить первое впечатление набросок

NB>>Кто до сюда дочитал, критикуйте

R>Слишком много кода


потому что без буста и с отладочной информацией.
у тебя чуть меньше, но в архивированном виде

R>См. здесь


видимо я неправильно понял задание
наш код производит разные манипуляции...

что-то не соображу после праздника:
R>        CharType retval = m_last_buffer << ShiftBits;
сдвигаем прошлое значение на ShiftBits получаем старшие разряды.

R>        retval += (unsigned)m_buffer >> (sizeof(base_value_type)*8-ShiftBits);
сдвигаем новое значение на 32-ShiftBits получаем младшие разряды. склеиваем.
может необходимо результат сдвинуть циклисески, чтобы из прошлое значение соответствовало
младшим разрядам?


надо будет подумать, когда отойду...
Re[5]: Пжалста :)
От: remark Россия http://www.1024cores.net/
Дата: 17.10.06 09:53
Оценка:
Здравствуйте, night beast, Вы писали:

NB>видимо я неправильно понял задание

NB>наш код производит разные манипуляции...

NB>что-то не соображу после праздника:

NB>
R>>        CharType retval = m_last_buffer << ShiftBits;
NB>сдвигаем прошлое значение на ShiftBits получаем старшие разряды.

R>>        retval += (unsigned)m_buffer >> (sizeof(base_value_type)*8-ShiftBits);
NB>сдвигаем новое значение на 32-ShiftBits получаем младшие разряды. склеиваем.
NB>может необходимо результат сдвинуть циклисески, чтобы из прошлое значение соответствовало
NB>младшим разрядам?
NB>


NB>надо будет подумать, когда отойду...


По-моему, нормально получилось Мне нравица, по крайне мере с тем, что я нарисовал на бумажке сходится
В принципе можно ещё сделать shr_iter (shl/sar/sal), что б сдвигал по вкусу
typedef transform_width<shr_iter<shift_iter<byte*, 3>, 4, 8, 2> my_iter;

Крысота


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Пжалста :)
От: night beast СССР  
Дата: 17.10.06 10:00
Оценка:
Здравствуйте, remark, Вы писали:

NB>>надо будет подумать, когда отойду...


R>По-моему, нормально получилось Мне нравица, по крайне мере с тем, что я нарисовал на бумажке сходится

R>В принципе можно ещё сделать shr_iter (shl/sar/sal), что б сдвигал по вкусу
R>
R>typedef transform_width<shr_iter<shift_iter<byte*, 3>, 4, 8, 2> my_iter;
R>

R>Крысота

а что ты нарисовал на бумажке?
Re[4]: Как сдвинуть указатель на несколько бит?
От: np9mi7 Россия  
Дата: 17.10.06 10:54
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Ну тогда надо вспомнить и про std::bitset

А>Способов решения проблемы автора топика — вагон и маленькая тележка...

Причем тут std::bitset? Туда битов ровно столько, сколько в long помещается, а автор говорит про массив char (не размером sizeof (long));
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Re[3]: Пжалста :)
От: Аноним  
Дата: 18.10.06 06:57
Оценка:
Здравствуйте, night beast, Вы писали:
NB>
NB>    template<typename T>
NB>    struct temporary {
NB>        T value;
NB>        explicit temporary ( T src ) : value (src) {}

NB>        T * operator -> () { return & this->value; }
NB>    };
NB>    temporary<reference> operator -> () const { return temporary<reference> ( reference (this->ptr) ); }
NB>
Re[3]: Пжалста :)
От: Аноним  
Дата: 18.10.06 07:01
Оценка:
Здравствуйте, night beast, Вы писали:
NB>
NB>    template<typename T>
NB>    struct temporary {
NB>        T value;
NB>        explicit temporary ( T src ) : value (src) {}

NB>        T * operator -> () { return & this->value; }
NB>    };
NB>    temporary<reference> operator -> () const { return temporary<reference> ( reference (this->ptr) ); }
NB>


Зачем нужен temporary?
Re[7]: Пжалста :)
От: remark Россия http://www.1024cores.net/
Дата: 18.10.06 07:36
Оценка:
Здравствуйте, night beast, Вы писали:

NB>а что ты нарисовал на бумажке?


ну там биты и их сдвиг...
и то, что я нарисовал, сошлось с тем, что выдаёт программа...


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Пжалста :)
От: night beast СССР  
Дата: 18.10.06 07:45
Оценка: 7 (1)
Здравствуйте, Аноним, Вы писали:

А>Зачем нужен temporary?


operator -> должен возвращать указатель или объект в перегруженым оператором -> (возвращающим указатель или и т.д., короче в конце все равно должен быть указатель)
возвращать указатель на локальный объект мы не можем, поэтому temporary продлевает время жизни этого объекта и обеспечивает нужную семантику.
Re[3]: Пжалста :)
От: Aleksej_A  
Дата: 20.10.06 17:18
Оценка:
Здравствуйте, night beast, Вы писали:


NB>собственно, чтобы сгладить первое впечатление набросок

NB>
NB>#include <iostream>
NB>#include <limits>
NB>#include <iterator>
NB>#include <bitset>

NB>template< int shift = 0 >
NB>struct shift_iterator
NB>{
NB>    typedef std::random_access_iterator_tag iterator_category;
NB>    typedef unsigned long value_type;
NB>    struct reference;
NB>    typedef ptrdiff_t difference_type;

NB>    value_type * ptr;

NB>    shift_iterator ( value_type * src ) : ptr (src) {}

NB>    reference operator * () const { return reference (this->ptr); }
NB>    reference operator [] (difference_type) const;

NB>    template<typename T>
NB>    struct temporary {
NB>        T value;
NB>        explicit temporary ( T src ) : value (src) {}

NB>        T * operator -> () { return & this->value; }
NB>    };
NB>    temporary<reference> operator -> () const { return temporary<reference> ( reference (this->ptr) ); }


NB>    shift_iterator & operator ++ () { ++this->ptr; return (*this); }
NB>    shift_iterator & operator -- () { --this->ptr; return (*this); }

NB>    shift_iterator operator ++ (int) { shift_iterator tmp (*this); ++(*this); return tmp; }
NB>    shift_iterator operator -- (int) { shift_iterator tmp (*this); --(*this); return tmp; }

NB>    shift_iterator & operator += ( difference_type n ) { this->ptr += n; return (*this); }
NB>    shift_iterator & operator -= ( difference_type n ) { this->ptr -= n; return (*this); }
NB>};

NB>template< int shift >
NB>struct shift_iterator<shift>::reference {
NB>    static const int digits = std::numeric_limits<value_type>::digits;
NB>    typedef std::bitset<digits> bitset;


NB>    value_type * ptr;
NB>    reference ( value_type * src ) : ptr (src) {}
NB>    value_type value () const { 

NB>        std::cout << __FUNCTION__ << std::endl;

NB>        bitset tmp (*this->ptr); // берем текущий элемент.
NB>        std::cout << tmp.to_ulong () << ":" << tmp << std::endl;
NB>        bitset val = tmp >> shift; // удаляем хвост предынущего элемента. теперь val хранит младшую часть значения.
NB>        std::cout << val.to_ulong () << ":" << val << std::endl;

NB>        tmp = *(this->ptr+1); // берем следующий элемент.
NB>        std::cout << tmp.to_ulong () << ":" << tmp << std::endl;
NB>        tmp = (tmp << digits-shift); // получаем старшую чась значения.
NB>        std::cout << tmp.to_ulong () << ":" << tmp << std::endl;
NB>        val |= tmp; // склеиваем младшую и старшую части.
NB>        std::cout << val.to_ulong () << ":" << val << std::endl;

NB>        return val.to_ulong ();  // возвращаем значение.
NB>    }

NB>    operator value_type () const { return this->value (); }

NB>    reference & operator = ( value_type value ) { 
NB>        static bitset const mask = bitset ().set(); // все единицы
NB>        static bitset const hmask= mask << shift; // старшая часть = единицы
NB>        static bitset const lmask= ~ hmask; // младшая часть = единицы

NB>        std::cout << __FUNCTION__ << std::endl;

NB>        std::cout << lmask << std::endl;
NB>        std::cout << hmask << std::endl;

NB>        bitset tmp (*this->ptr); // берем текущий элемент.
NB>        bitset val (value); // и новое значение.

NB>        std::cout << tmp.to_ulong () << ":" << tmp << std::endl;
NB>        std::cout << val.to_ulong () << ":" << val << std::endl;
NB>        val = ( val << shift ) | ( val >> digits-shift ); // для удобства сдвигаем циклически новое значение на число бит.
NB>        std::cout << val << std::endl;
NB>        tmp = ( tmp & lmask ) | ( val & hmask ); // склеиваем хвост предыдущего элемента и младшую часть нового значения.
NB>        std::cout << tmp << std::endl;
NB>        *this->ptr = tmp.to_ulong (); // записываем в текущий элемент это значение.

NB>        tmp = *(this->ptr+1); // берем следующий элемент.
NB>        std::cout << tmp.to_ulong () << ":" << tmp << std::endl;
NB>        tmp = ( val & lmask ) | ( tmp & hmask ); // склеиваем старшую часть нового значения и начало следующего элемента.
NB>        std::cout << tmp << std::endl;
NB>        *(this->ptr+1) = tmp.to_ulong (); // записываем полученное значение в массив.

NB>        return (*this); 
NB>    }

NB>};

NB>int main() { 
NB>    unsigned long x[4] = {7,5,3,5};
NB>    shift_iterator<2> it (x);
NB>    std::cout << it->value () << std::endl;
NB>    *it = std::numeric_limits<unsigned long>::max()-4;

NB>    return 0;
NB>}
NB>



NB>Предупреждаю сразу.

NB>У итератора не хватает операций +,-, и операций сравнения. Добавить не сложно много но ручной работы.
NB>bitset применял для наглядности. поэтому его лучше заменить непосредственно на value_type.

NB>Кто до сюда дочитал, критикуйте



Н-да, код суровый!
Чтобы не заводить новой ветки, спрошу здесь...
В задаче есть условие, что символы кодируются N-ным числом бит, например 3 битами.
Коды символов:
S1=000
S2=001
S3=010
S4=011
S5=100
Последовательность символов S1 S2 S3 S1 S4 S1 S5 S1 S2 S3 S1 кодируется битами так :
000 001 010 000 011 000 100 000 001 010 000, а если представить это байтами и добавить 7 нулевых битов в конец, чтобы дополнить неполный 5-ый бит, то получим 05 06 20 28 00.

То есть нужен некий класс BitWriter<Nbits>, который получает последовательность байт, определяет их код и пишет в поток битами по Nbits. В приведенном случае Nbits=3.
Думал реализовать с использованием шаблона bitset<size_t N>, но у него фиксированный размер

В этой ветке и еще тут
Автор: mxc
Дата: 18.10.06
были темы отдаленно напоминающие то, что мне нужно ...
Заранее спасибо за любые идеи.
Re[4]: Пжалста :)
От: night beast СССР  
Дата: 21.10.06 09:34
Оценка:
Здравствуйте, Aleksej_A, Вы писали:

A_A>Н-да, код суровый!


Не очень. Даже коментарии есть.
Однако не стоило его цитировать полностью...

A_A>То есть нужен некий класс BitWriter<Nbits>, который получает последовательность байт, определяет их код и пишет в поток битами по Nbits. В приведенном случае Nbits=3.

A_A>Думал реализовать с использованием шаблона bitset<size_t N>, но у него фиксированный размер

А не попробовать ли boost::dynamic_bitset ?
Re[5]: Пжалста :)
От: Aleksej_A  
Дата: 21.10.06 17:51
Оценка:
Здравствуйте, night beast, Вы писали:


A_A>>То есть нужен некий класс BitWriter<Nbits>, который получает последовательность байт, определяет их код и пишет в поток битами по Nbits. В приведенном случае Nbits=3.

A_A>>Думал реализовать с использованием шаблона bitset<size_t N>, но у него фиксированный размер

NB>А не попробовать ли boost::dynamic_bitset ?

Спасибо, хорошее средство для моей задачи. Но при беглом взгляде обнаружил такую особенность :

unsigned char ch = 0xF0;

dynamic_bitset<> dbs1(1000);
dbs1 <<= sizeof(unsigned char);

dbs1 |= ch; //не работает, когда хочу добавить 8 бит в конец битсета

dynamic_bitset<> dbs_for_ch_storage(8, static_cast<unsigned long int>(ch));
dbs1 |= dbs_for_ch_storage; //не работает(вернее кидает exception), ибо если dbs1 1000 бит, то и dbs_for_ch_storage должен быть 1000 бит

dynamic_bitset<> dbs_for_ch_storage(1000, static_cast<unsigned long int>(ch));
dbs1 |= dbs_for_ch_storage;


То-есть, чтоб совершить операцию с dbs1 и числом, для этого числа надо создать битсет-хранилище, размером с dbs1 ??
Re[6]: Пжалста :)
От: night beast СССР  
Дата: 21.10.06 19:21
Оценка:
Здравствуйте, Aleksej_A, Вы писали:

NB>>А не попробовать ли boost::dynamic_bitset ?

A_A>Спасибо, хорошее средство для моей задачи. Но при беглом взгляде обнаружил такую особенность :

Несколько слов человека, не разу не пользовавшегося этой бибиотекой:

A_A>unsigned char ch = 0xF0;

A_A>dynamic_bitset<> dbs1(1000);

если работаешь с чарами, то наверно dynamic_bitset<unsigned char>

A_A>dbs1 <<= sizeof(unsigned char);

если ты думаешь, что он сдвинет на 8 бит, то должен огорчить. sizeof(unsigned char) == 1;
используй std::numeric_limits<unsigned char>::digints;

A_A>dbs1 |= ch; //не работает, когда хочу добавить 8 бит в конец битсета

если хочешь добавить в конец, то для этого есть функция append (Block).


A_A>То-есть, чтоб совершить операцию с dbs1 и числом, для этого числа надо создать битсет-хранилище, размером с dbs1 ??


примитивы для работы с битами там есть. добавить нужную функциональность проблем не составит.
не совсем понятна цель. bitset -- это контейнер битов. вот и работай с ним как с контейнером.
Re: Как сдвинуть указатель на несколько бит?
От: Erlond Россия  
Дата: 22.10.06 13:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Есть массив элементов типа unsigned long int DI[100]; есть указатель на начало массива unsigned char *ptr; можно ли сдвинуть указатель на несколько битов вперед относительно начала массива, так чтобы он указывал допустим на 3-й бит первого элемента массива? и как это реализовать? Заранее спасибо.


Сдинуть указатель на несколько бит невозможно на процессорах х86, это связано с тем, что меньше одного байта процессор адресовать не может.
В общем случае способов решения существуе достаточно много, но было бы легче что-то посоветовать, если бы была более общая постановка задачи, возможно что вообще не потребуется проверять 3-й бит.

P.S. самый простой вариант:

long int DI[100];
const long int mask = 4; // для того, чтобы 4 точно гарантированно тип long int
bool third_bit_value = (DI[n] & mask)? true : false;

4 в двоичной системе счилления 100, т.о выделяем значение 3-го бита
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.