Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 58, средняя оценка - 4.74
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
#1

Битовые поля - C++

09.01.2012, 05:21. Просмотров 8084. Ответов 19
Метки нет (Все метки)

В приложении 1 есть пример использования битовых полей. В выделенной строке структуре присваивается бит, полученный из функции. (Кстати, как функция может вернуть БИТ?) Чтобы обеспечить возможность такого присваивания, функция должна возвращать значение такого же типа, как принимающий его объект структуры. Почему же возможно обойтись и без этого, так, как описано в приложении 1? По аналогии написал программу:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    struct {
        binary digit0:1;
        binary digit1:1;
        binary digit2:1;
        binary digit3:1;
        binary digit4:1;
        binary digit5:1;
        binary digit6:1;
        binary digit7:1;
    } str;
    
    str = 'A';
    cout << "A: ";
 
    if(str.digit0) cout << 1;
    if(str.digit1) cout << 1;
    if(str.digit2) cout << 1;
    if(str.digit3) cout << 1;
    if(str.digit4) cout << 1;
    if(str.digit5) cout << 1;
    if(str.digit6) cout << 1;
    if(str.digit7) cout << 1;
Но она не компилируется с ошибкой
Код
C2679: binary '=' : no operator defined which takes a right-hand operand of type 'const char' (or there is no acceptable conversion)
В приложении 2 приведен код программы использующей объединение для перестановки двух байтов (sb.ch[0] и sb.ch[1]) в рамках короткого целого значения (sb.num = 15). 15 == 1111d, тогда в sb.ch[0] будет 00000000, а в sb.ch[1] - 00001111. Но тогда при выводе начального состояния битов будет выведено 00001111 00000000, а не 00000000 00001111. Почему же все-таки получается так, как описано в приложении 2?

И существует ли способ объявить битовое поле с помощью перечисления?
0
Миниатюры
Битовые поля   Битовые поля  
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.01.2012, 05:21
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Битовые поля (C++):

Битовые операции, битовые поля. - C++
Здравствуйте! Еслть 4 диапазона чисел: 0-100, 0-100, 0-6000, 0-3. Сделать в виде битовых операций. Записать в unsigned int. Использовать...

Битовые поля. Поля без типа и имени - C++
Вчера сделал очень интересную и болезненную ошибку (с точки зрения времени, так как искал я ее долго)... представьте структуру (битовое...

битовые поля!! - C++
добрый вечер! имеется класс представления битовых полей: #ifndef HTBITFIELDS #define HTBITFIELDS #include &lt;iostream&gt; using...

Битовые поля - C++
struct TKeyFlags { int Old :1; int :6; int ...

С++ битовые поля - C++
Написал код в котором используется характеристический вектор, все компилиться и вроде бы все замечательно, но мне нужен 20битный тип, а не...

Битовые поля - C++
Здравствуйте, расскажите мне пожалуйста как происходят операции с битами. Мне необходимо получить 1 байт, разделить его на 2 битовых поля...

19
DU
1483 / 1129 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
09.01.2012, 05:27 #2
ругается на строку
C++
1
 str = 'A';
str имеет тип хз какой, в общем структура какая-то, а 'A' имеет тип char.
У структуры по умолчанию нет оператора =, который бы слева принимал тип char.
для работы с битами в с++ есть bitset. наверно лучше его заюзать.
0
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
09.01.2012, 05:46  [ТС] #3
Эээ, ну да, ругается на эту строку. В приложение смотрел пример? Повторю, функция возвращает бит, который присваивается битовым полям через структуру. Хотелось бы узнать про механизм таких действий. Вот по аналогии структура тип char не хочет получать, а вот бит - получает!

Цитата Сообщение от DU Посмотреть сообщение
есть bitset
Если это на 3 часть, то интересуют именно битовые поля в связке с перечислением.
0
Evg
Эксперт CАвтор FAQ
18032 / 6264 / 427
Регистрация: 30.03.2009
Сообщений: 17,229
Записей в блоге: 28
09.01.2012, 12:25 #4
Цитата Сообщение от Tamoren Посмотреть сообщение
В приложение смотрел пример?
Выделенное красным возвращает структуру, а не бит. Бит (как и байт) возвращать нельзя. Возвращать можно только значение какого-либо существующего типа языка

Добавлено через 3 минуты
Да и вообще, в данной теме ТС'у нелишним будет напомнить, что грамотно поставленный вопрос - это уже половина ответа

Цитата Сообщение от Tamoren Посмотреть сообщение
Но тогда при выводе начального состояния битов будет выведено 00001111 00000000, а не 00000000 00001111
Обрати внимание, что печатается сначала ch[1], а потом ch[0] (а не наоборот). Это связано с тем, что intel'овские процессоры - little endian
2
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
09.01.2012, 16:36  [ТС] #5
Цитата Сообщение от Evg Посмотреть сообщение
Бит (как и байт) возвращать нельзя
Да-да, там был байт.. (так прям и написано, может возвращать байт состояния) Получается, что выводимый функцией тип структуры "случайно" совпал с типом, приведенным в книге?

Цитата Сообщение от Evg Посмотреть сообщение
Обрати внимание, что печатается сначала ch[1], а потом ch[0] (а не наоборот). Это связано с тем, что intel'овские процессоры - little endian
Обратил, поэтому результат привел меня в ступор. Параграфом ранее была картинка, на которой были расположены два байта (слева направо), и переменна i владела обоими байтами, а ch (не массив, а одна переменная) только первым, поэтому я решил, что идет по возрастанию. Получается, что сначала идет sb.ch[1], а потом sb.ch[0]! На википедии про битовые поля сказано "[старший бит] d d d d c c b a [младший бит]". Похоже, как и биты, так и байты идут справа налево О_о. Посмотрел про little endian. Но следуя этой картинке, должно быть слева направо! http://ru.wikipedia.org/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Endianmem.PNG

И все-таки существует ли способ объявить битовое поле с помощью перечисления?
0
Evg
Эксперт CАвтор FAQ
18032 / 6264 / 427
Регистрация: 30.03.2009
Сообщений: 17,229
Записей в блоге: 28
09.01.2012, 17:01 #6
Цитата Сообщение от Tamoren Посмотреть сообщение
Получается, что выводимый функцией тип структуры "случайно" совпал с типом, приведенным в книге?
Он не случайно совпал, а потому, что размер структуры равен одному байту. Можно написать функцию, которая возвращает char или unsigned char. Можно написать функцию, которая возвращает структуру размером 1 байт. Все эти функции будут возвращать разные типы значений. Но у всех размер будет равен 1 байту. Поэтому сказать, что "функция возвращает байт" - это почти не сказать ничего

Цитата Сообщение от Tamoren Посмотреть сообщение
Похоже, как и биты, так и байты идут справа налево
Биты в принципе не могут идти слева направо или справа налево. Потому что биты - НЕ адресуемые единицы. Я не знаю, что написано на википедии, я никогда не считал её источником, в котором нужно черпать истину. Как битовые поля разложены в памяти в случае little-endian - смотри тут в случае big-endian - тут на картинке 3-10 (да и вообще можно весь раздел почитать). Разложение полей структуры - это не свойство языка, а свойство программных соглашений (ABI) на каждую конкретную архитектуру. Но по факту почти на всех современных процессорах используются одни и те же соглашения по распределению структур с точностью до выравнивания типов языка и распределения битовых полей для разных endian'ов.

Цитата Сообщение от Tamoren Посмотреть сообщение
И все-таки существует ли способ объявить битовое поле с помощью перечисления?
Я тебе уже говорил: пока ты внятно не сформулируешь вопрос, никто тебе на него не ответит, потому что никто не понимает, чего ты хочешь
1
alex_x_x
бжни
2449 / 1654 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
09.01.2012, 17:08 #7
должно быть видимо както так

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
typedef bool binary;
 
typedef struct {
                binary digit0:1;
                binary digit1:1;
                binary digit2:1;
                binary digit3:1;
                binary digit4:1;
                binary digit5:1;
                binary digit6:1;
                binary digit7:1;
        } bits;
 
void print_bit(bool bit)
{
    cout << (bit ? 1 : 0);
}
 
int main()
{       
        char a = 'A';
        bits str;
        memcpy (&str, &a, 1);
        cout << "A: (" << (unsigned)a << ") ";
 
        print_bit (str.digit7);
        print_bit (str.digit6);
        print_bit (str.digit5);
        print_bit (str.digit4);
        print_bit (str.digit3);
        print_bit (str.digit2);
        print_bit (str.digit1);
        print_bit (str.digit0);
        
}
1
Evg
Эксперт CАвтор FAQ
18032 / 6264 / 427
Регистрация: 30.03.2009
Сообщений: 17,229
Записей в блоге: 28
09.01.2012, 17:11 #8
Ну и до кучи. В языке Си поведение битовых полей определено только для unsigned int, а всё остальное - то ли implementation defined, то ли unspecified. Но по факту все нормальные компиляторы нормально работают с битовыми полями любого типа. Может в стандарте Си++ всё по человечески описано
0
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
09.01.2012, 21:36  [ТС] #9
Цитата Сообщение от Evg Посмотреть сообщение
размер структуры равен одному байту
Цитата Сообщение от Evg Посмотреть сообщение
функцию, которая возвращает структуру размером 1 байт
Так пусть возвращает, на здоровье! Но если мы захотим этот байт присвоить структуре из битовых полей, мы должны быть уверены, что возвращаемые функцией данные размером в байт такого же типа, как и структура из битовых полей. Чтобы доказать, что эта структура должна получать данные не абы какого типа, я и написал программу, в которой присваивал такой же структуре константу типа char размером в байт. Получилась ошибка. Значит функция get_port_status() должна возвращать структуру такого же типа, как и принимающая.

Цитата Сообщение от Evg Посмотреть сообщение
Биты в принципе не могут идти слева направо или справа налево
Гм... я не правильно выразился. Вот, здесь объявляются битовые поля a,b,c,d (именно в этом порядке), которые занимают вместе 1 байт. Причем в этом байте они расположены в обратном порядке (см. ссылку). Кстати, по ссылке на little-endian самую первую (левую) позицию занимает самое последнее битовое поле!

В общем получается (исходя из результатов программы), что в памяти идет ch[1], а потом ch[0]. И вовсе не так, как указано на рисунке (см. приложение). Всё, я запутался

Есть перечисление:
C++
1
2
3
4
    enum binary {
        Zero,
        One
    };
Можно ли с его помощью объявить структуру? Например так?
C++
1
2
3
4
5
6
7
8
9
10
    struct {
        binary digit0:1;
        binary digit1:1;
        binary digit2:1;
        binary digit3:1;
        binary digit4:1;
        binary digit5:1;
        binary digit6:1;
        binary digit7:1;
    } str;
0
Evg
Эксперт CАвтор FAQ
18032 / 6264 / 427
Регистрация: 30.03.2009
Сообщений: 17,229
Записей в блоге: 28
09.01.2012, 21:47 #10
Цитата Сообщение от Tamoren Посмотреть сообщение
Так пусть возвращает, на здоровье! Но если мы захотим этот байт присвоить структуре из битовых полей, мы должны быть уверены, что возвращаемые функцией данные размером в байт такого же типа, как и структура из битовых полей. Чтобы доказать, что эта структура должна получать данные не абы какого типа, я и написал программу, в которой присваивал такой же структуре константу типа char размером в байт. Получилась ошибка. Значит функция get_port_status() должна возвращать структуру такого же типа, как и принимающая
Если кто-то что-нибудь понял, поднимите руку. Я не понял вообще ничего

Цитата Сообщение от Tamoren Посмотреть сообщение
Можно ли с его помощью объявить структуру? Например так?
Можно (если на си++). Если на си, то правильно писать "enum binary digit0:1". Только не пойму, что тебе мешало взять и проверить?
1
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
09.01.2012, 22:35  [ТС] #11
Черт... Это все про первое приложение. В карсной рамочке выделено то, что я никак не могу понять. Вопрос заключается в том, как битовые поля "догадались" как им принимать значения, если им пытаются присвоить 1 байт информации неизвестно какого типа, причем врятли такого же, как у структуры (которой собственно и присваивают).

Цитата Сообщение от Evg Посмотреть сообщение
что тебе мешало взять и проверить?
Я проверил, компилятор на это ошибки не выдавал, просто ещё не до конца выяснил, как эти битовые поля работают, чтобы им что то можно было присвоить. Если только вручную.
0
Evg
Эксперт CАвтор FAQ
18032 / 6264 / 427
Регистрация: 30.03.2009
Сообщений: 17,229
Записей в блоге: 28
09.01.2012, 23:12 #12
Цитата Сообщение от Tamoren Посмотреть сообщение
Черт... Это все про первое приложение. В карсной рамочке выделено то, что я никак не могу понять. Вопрос заключается в том, как битовые поля "догадались" как им принимать значения, если им пытаются присвоить 1 байт информации неизвестно какого типа, причем врятли такого же, как у структуры (которой собственно и присваивают).
У тебя есть присваивание. В левой части присваивания переменная status которая имеет тип struct status_type, в правой части присваивания - функция get_port_status, которая возвращает результат типа struct status_type, а не "неизвестно какой тип". Если бы был неизвестно какой тип, то программа бы не скомпилировалась, потому что компилятор не знает, каким образом можно неизвестно какой тип записать в конкретную структуру. Если я правильно понял вопрос
1
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
09.01.2012, 23:54  [ТС] #13
Вот!! Именно это я и имел ввиду. Если все заработало, значит эта функция возвращает результат типа struct status_type, ч т.д. Просто в книге не было написано про это. Было сказано, что "возвращает байт", что и повергло меня в ступор! И именно к этому я писал, что тип "случайно" совпал (подразумевая, что совпал он совсем не случайно, а автор книги просто не написал об этом). Спасибо!!

Добавлено через 6 минут
Осталось только это:
Цитата Сообщение от Tamoren Посмотреть сообщение
Гм... я не правильно выразился. Вот, здесь объявляются битовые поля a,b,c,d (именно в этом порядке), которые занимают вместе 1 байт. Причем в этом байте они расположены в обратном порядке (см. ссылку). Кстати, по ссылке на little-endian самую первую (левую) позицию занимает самое последнее битовое поле!
В общем получается (исходя из результатов программы), что в памяти идет ch[1], а потом ch[0]. И вовсе не так, как указано на рисунке (см. приложение). Всё, я запутался
Если я например сделаю:
C++
1
2
3
4
union uni_type{
    int a;
    char ch[4];
}uni;
То у меня на месте памяти, занимаемой a будет распологаться ch[3], ch[2], ch[1], ch[0] именно в таком порядке? Это же и есть little-endian! И массив (при заполнении от 0 к 3) будет заполняться справа налево? Нигде не наврал?
0
alkagolik
Заблокирован
10.01.2012, 00:02 #14
Tamoren,
C
1
2
3
int i = 0;
while ( i < 4 )
    printf( "%x\n", &uni.ch[ i++ ] );
1
alex_x_x
бжни
2449 / 1654 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
10.01.2012, 00:28 #15
Tamoren, в своем примере вы не путаете байты с битами?
первоначально речь же шла про биты
0
10.01.2012, 00:28
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.01.2012, 00:28
Привет! Вот еще темы с ответами:

Битовые поля - C++
Программа,представляет с собой структуру ломбарда т.е:. База хранимых товаров и недвижимости: анкетные данные клиента, наименование товара,...

Битовые поля - C++
Подскажмте пожалуйста новичку, что такое битовые поля.Уже перечитываю раз 11ый, а никак понять не могу. Скажите пожалуйста популярным...

Битовые поля - C++
Здравствуйте. Возникла необходимость работы с битовыми полями. Однако не могу понять, почему в нижеприведенном примере биты...

битовые поля - C++
пользователь вводит с клавиатуры 2 беззнаковых длинных целых числа a, b. Вывести на консоль множества A, B, которые представляют битовые...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru