Есть массив элементов типа unsigned long int DI[100]; есть указатель на начало массива unsigned char *ptr; можно ли сдвинуть указатель на несколько битов вперед относительно начала массива, так чтобы он указывал допустим на 3-й бит первого элемента массива? и как это реализовать? Заранее спасибо.
Здравствуйте, Аноним, Вы писали:
А>Есть массив элементов типа 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-й бит первого элемента массива? и как это реализовать? Заранее спасибо.
Для этого достаточно обычных указателей и побитовых операций.
Указателей не "биты" не существует.
Здравствуйте, Аноним, Вы писали:
А>Мне надо найти в массиве DI запрашиваемый бит и шагать побайтно, потом с полученными данными дальше работать. Мне надо реализовать вторую функцию Modbus.
Найди этот бит, а потом передвинь все элементы так, чтобы получился нормальный массив, в котором и будет ptr++;
Re[4]: Как сдвинуть указатель на несколько бит?
От:
Аноним
Дата:
16.10.06 06:55
Оценка:
Как передвинуть, используя операции сдвига? можно подробней7
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Здравствуйте, <Аноним>, Вы писали:
А>Мне надо найти в массиве DI запрашиваемый бит и шагать побайтно, потом с полученными данными дальше работать. Мне надо реализовать вторую функцию Modbus.
Напиши адаптер. Степень адаптации может варьироваться — начиная от просто побайтового чтения
Здравствуйте, Аноним, Вы писали:
А>Есть массив элементов типа unsigned long int DI[100]; есть указатель на начало массива unsigned char *ptr; можно ли сдвинуть указатель на несколько битов вперед относительно начала массива, так чтобы он указывал допустим на 3-й бит первого элемента массива? и как это реализовать? Заранее спасибо.
А>>Есть массив элементов типа unsigned long int DI[100]; есть указатель на начало массива unsigned char *ptr; можно ли сдвинуть указатель на несколько битов вперед относительно начала массива, так чтобы он указывал допустим на 3-й бит первого элемента массива? и как это реализовать? Заранее спасибо.
А>Для этого достаточно обычных указателей и побитовых операций. А>Указателей не "биты" не существует.
Здравствуйте, 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.
Здравствуйте, Аноним, Вы писали:
А>Есть массив элементов типа unsigned long int DI[100]; есть указатель на начало массива unsigned char *ptr; можно ...
Для реализации МодБас необязательно хранить ячейки в упакованном виде, хотя у меня кеш так и реализован, а можно в виде массива 32-х битных интежеров. Заодно получите возможность хранить неопределённые состояния.
Здравствуйте, remark, Вы писали:
R>Здравствуйте, night beast, Вы писали:
NB>>собственно, чтобы сгладить первое впечатление набросок NB>>Кто до сюда дочитал, критикуйте
R>Слишком много кода
R>См. здесь
R>
Здравствуйте, 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 получаем младшие разряды. склеиваем.
может необходимо результат сдвинуть циклисески, чтобы из прошлое значение соответствовало
младшим разрядам?
Здравствуйте, 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), что б сдвигал по вкусу
Здравствуйте, remark, Вы писали:
NB>>надо будет подумать, когда отойду...
R>По-моему, нормально получилось Мне нравица, по крайне мере с тем, что я нарисовал на бумажке сходится R>В принципе можно ещё сделать shr_iter (shl/sar/sal), что б сдвигал по вкусу R>
Здравствуйте, <Аноним>, Вы писали:
А>Ну тогда надо вспомнить и про std::bitset А>Способов решения проблемы автора топика — вагон и маленькая тележка...
Причем тут std::bitset? Туда битов ровно столько, сколько в long помещается, а автор говорит про массив char (не размером sizeof (long));
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Здравствуйте, Аноним, Вы писали:
А>Зачем нужен temporary?
operator -> должен возвращать указатель или объект в перегруженым оператором -> (возвращающим указатель или и т.д., короче в конце все равно должен быть указатель)
возвращать указатель на локальный объект мы не можем, поэтому temporary продлевает время жизни этого объекта и обеспечивает нужную семантику.
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>, но у него фиксированный размер
Здравствуйте, Aleksej_A, Вы писали:
A_A>Н-да, код суровый!
Не очень. Даже коментарии есть.
Однако не стоило его цитировать полностью...
A_A>То есть нужен некий класс BitWriter<Nbits>, который получает последовательность байт, определяет их код и пишет в поток битами по Nbits. В приведенном случае Nbits=3. A_A>Думал реализовать с использованием шаблона bitset<size_t N>, но у него фиксированный размер
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 ??
Здравствуйте, 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 -- это контейнер битов. вот и работай с ним как с контейнером.
Здравствуйте, Аноним, Вы писали:
А>Есть массив элементов типа 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-го бита