Как сдвинуть указатель на несколько бит?
От: Аноним  
Дата: 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-х битных интежеров. Заодно получите возможность хранить неопределённые состояния.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.