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

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

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 58, средняя оценка - 4.74
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
09.01.2012, 05:21     Битовые поля #1
В приложении 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?

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

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

Цитата Сообщение от DU Посмотреть сообщение
есть bitset
Если это на 3 часть, то интересуют именно битовые поля в связке с перечислением.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16824 / 5245 / 319
Регистрация: 30.03.2009
Сообщений: 14,121
Записей в блоге: 26
09.01.2012, 12:25     Битовые поля #4
Цитата Сообщение от Tamoren Посмотреть сообщение
В приложение смотрел пример?
Выделенное красным возвращает структуру, а не бит. Бит (как и байт) возвращать нельзя. Возвращать можно только значение какого-либо существующего типа языка

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

Цитата Сообщение от Tamoren Посмотреть сообщение
Но тогда при выводе начального состояния битов будет выведено 00001111 00000000, а не 00000000 00001111
Обрати внимание, что печатается сначала ch[1], а потом ch[0] (а не наоборот). Это связано с тем, что intel'овские процессоры - little endian
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%...:Endianmem.PNG

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

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

Цитата Сообщение от Tamoren Посмотреть сообщение
И все-таки существует ли способ объявить битовое поле с помощью перечисления?
Я тебе уже говорил: пока ты внятно не сформулируешь вопрос, никто тебе на него не ответит, потому что никто не понимает, чего ты хочешь
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
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);
        
}
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16824 / 5245 / 319
Регистрация: 30.03.2009
Сообщений: 14,121
Записей в блоге: 26
09.01.2012, 17:11     Битовые поля #8
Ну и до кучи. В языке Си поведение битовых полей определено только для unsigned int, а всё остальное - то ли implementation defined, то ли unspecified. Но по факту все нормальные компиляторы нормально работают с битовыми полями любого типа. Может в стандарте Си++ всё по человечески описано
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;
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16824 / 5245 / 319
Регистрация: 30.03.2009
Сообщений: 14,121
Записей в блоге: 26
09.01.2012, 21:47     Битовые поля #10
Цитата Сообщение от Tamoren Посмотреть сообщение
Так пусть возвращает, на здоровье! Но если мы захотим этот байт присвоить структуре из битовых полей, мы должны быть уверены, что возвращаемые функцией данные размером в байт такого же типа, как и структура из битовых полей. Чтобы доказать, что эта структура должна получать данные не абы какого типа, я и написал программу, в которой присваивал такой же структуре константу типа char размером в байт. Получилась ошибка. Значит функция get_port_status() должна возвращать структуру такого же типа, как и принимающая
Если кто-то что-нибудь понял, поднимите руку. Я не понял вообще ничего

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

Цитата Сообщение от Evg Посмотреть сообщение
что тебе мешало взять и проверить?
Я проверил, компилятор на это ошибки не выдавал, просто ещё не до конца выяснил, как эти битовые поля работают, чтобы им что то можно было присвоить. Если только вручную.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16824 / 5245 / 319
Регистрация: 30.03.2009
Сообщений: 14,121
Записей в блоге: 26
09.01.2012, 23:12     Битовые поля #12
Цитата Сообщение от Tamoren Посмотреть сообщение
Черт... Это все про первое приложение. В карсной рамочке выделено то, что я никак не могу понять. Вопрос заключается в том, как битовые поля "догадались" как им принимать значения, если им пытаются присвоить 1 байт информации неизвестно какого типа, причем врятли такого же, как у структуры (которой собственно и присваивают).
У тебя есть присваивание. В левой части присваивания переменная status которая имеет тип struct status_type, в правой части присваивания - функция get_port_status, которая возвращает результат типа struct status_type, а не "неизвестно какой тип". Если бы был неизвестно какой тип, то программа бы не скомпилировалась, потому что компилятор не знает, каким образом можно неизвестно какой тип записать в конкретную структуру. Если я правильно понял вопрос
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) будет заполняться справа налево? Нигде не наврал?
alkagolik
 Аватар для alkagolik
1510 / 616 / 79
Регистрация: 15.07.2011
Сообщений: 3,552
10.01.2012, 00:02     Битовые поля #14
Tamoren,
C
1
2
3
int i = 0;
while ( i < 4 )
    printf( "%x\n", &uni.ch[ i++ ] );
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
10.01.2012, 00:28     Битовые поля #15
Tamoren, в своем примере вы не путаете байты с битами?
первоначально речь же шла про биты
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
10.01.2012, 00:57  [ТС]     Битовые поля #16
Где именно? Я то про байты, то про биты...
Хм.. У меня &uni.ch[i++] вводит иероглифы. Как мне привести полученный адрес к hex виду?
alkagolik
 Аватар для alkagolik
1510 / 616 / 79
Регистрация: 15.07.2011
Сообщений: 3,552
10.01.2012, 00:58     Битовые поля #17
Цитата Сообщение от Tamoren Посмотреть сообщение
Где именно?
Цитата Сообщение от Tamoren Посмотреть сообщение
То у меня на месте памяти, занимаемой a будет распологаться ch[3], ch[2], ch[1], ch[0] именно в таком порядке? Это же и есть little-endian!
вот тут ты путаешь байты с битами.
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
10.01.2012, 01:22  [ТС]     Битовые поля #18
Всмысле? a - 4 байта, ch[0] - 1 байт, little-endian - про байты!
alkagolik
 Аватар для alkagolik
1510 / 616 / 79
Регистрация: 15.07.2011
Сообщений: 3,552
10.01.2012, 01:28     Битовые поля #19
вот что показала проверка
test.c
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
36
37
38
39
40
41
42
43
44
45
46
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
struct str_type {
    unsigned ch0:   8;
    unsigned ch1:   8;
    unsigned ch2:   8;
    unsigned ch3:   8;
} obj;
 
struct str {
    char ch[ 4 ];
} str1;
 
int main ( void )
{
    char ch[ 4 ];
    unsigned x = 0x11223344;
    memcpy( &obj, &x, sizeof( unsigned ) );
    memcpy( &str1, &x, sizeof( unsigned ) );
    memcpy( &ch, &x, sizeof( unsigned ) );
 
    printf( "%x\n", obj.ch0 );
    printf( "%x\n", obj.ch1 );
    printf( "%x\n", obj.ch2 );
    printf( "%x\n\n", obj.ch3 );
    printf( "%x\n", str1.ch[ 0 ] );
    printf( "%x\n", str1.ch[ 1 ] );
    printf( "%x\n", str1.ch[ 2 ] );
    printf( "%x\n\n", str1.ch[ 3 ] );
    printf( "%p\n", &str1.ch[ 0 ] );
    printf( "%p\n", &str1.ch[ 1 ] );
    printf( "%p\n", &str1.ch[ 2 ] );
    printf( "%p\n", &str1.ch[ 3 ] );
    printf( "%x\n", ch[ 0 ] );
    printf( "%x\n", ch[ 1 ] );
    printf( "%x\n", ch[ 2 ] );
    printf( "%x\n\n", ch[ 3 ] );
    printf( "%p\n", &ch[ 0 ] );
    printf( "%p\n", &ch[ 1 ] );
    printf( "%p\n", &ch[ 2 ] );
    printf( "%p\n", &ch[ 3 ] );
 
    return 0;
}

stdout
Код
44
33
22
11

44
33
22
11

0x804a024
0x804a025
0x804a026
0x804a027
44
33
22
11

0xbfc6f588
0xbfc6f589
0xbfc6f58a
0xbfc6f58b


Добавлено через 4 минуты
так что я похоже ошибался или не понял замечание alex_x_x. Посыпаю голову пеплом.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.01.2012, 00:43     Битовые поля
Еще ссылки по теме:

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

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

Или воспользуйтесь поиском по форуму:
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
12.01.2012, 00:43  [ТС]     Битовые поля #20
Всё, наконец разобрался и понял.

Массив char ch[] идет в естесственном порядке, а вот значение int a записывается "задом на перед" в плане байтов (это и есть little-endian). То есть если в массиве символы идут A, B, C, D, то в памяти байты, занимаемые значением int a идут (D)(C)(B)(A).

Что касается битовых полей, то если мы объявляем (и инициализируем далее) bit0, bit1, bit2, ..., bitn, то вычисляется их размер в байтах (округляется до целых в большую сторону), и в первом байте на последнюю позицию (разряд едениц) "пишется" bit0, далее байт заполняется слева направо до конца (до bit7) и bit8 "пишется" в последнюю позицию второго байта, и т.д.

Как то так. Все, что я здесь написал основано на опытах и является только предположением

А вот это действительно неверно:
Цитата Сообщение от Tamoren Посмотреть сообщение
То у меня на месте памяти, занимаемой a будет распологаться ch[3], ch[2], ch[1], ch[0] именно в таком порядке
Yandex
Объявления
12.01.2012, 00:43     Битовые поля
Ответ Создать тему
Опции темы

Текущее время: 13:26. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru