Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
1

sizeof на битовую структуру

20.10.2012, 07:38. Показов 2130. Ответов 27
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Данный код структуры :
C++
1
2
3
4
5
6
7
8
#pragma pack(push, 1)
 
struct FIELD
{ 
    unsigned x : BITS_COUNT; 
};
 
#pragma pack(pop)
воспринимается
C++
1
sizeof(FIELD);
как 4 байта, где
C++
1
#define BITS_COUNT 24
Вопрос : почему?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.10.2012, 07:38
Ответы с готовыми решениями:

Sizeof(.) или constexpr size_t tmp = sizeof(.)
sizeof(...) или constexpr size_t tmp = sizeof(...) Как лучше с точки зрения производительности?...

Fwrite (buffer , sizeof(char), sizeof(buffer), pFile)
как записать часть массива чаров? допустим у нас arr; мне надо записать с позиции массива 500 до...

Можно ли на 32 битовую систему установить 64 битовую sql server?
можно ли на 32 битовую систему установить 64 битовую sql server?

Как установить 32 битовую версию на 64 битовую ОС?
Проблема с установкой связи из МАТЛАБ к SQL server 2008. Win 64, МАаТЛАБ 64 и SQL server 64 бита....

27
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
21.10.2012, 10:37 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от Герц Посмотреть сообщение
Это лучше чем каждый бит или несколько вытаскивать по маске и выравнивать оператором сдвига.
Вот как раз нет. Лучше (с точки зрения эффективности кода) делать это именно ручками. В идеале, оформив в виде класса и inline методами. Битовые поля крайне неэффективны (по крайней мере там было в течении многих веков, возможно это уже не является проблемой для компилятора).
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
21.10.2012, 10:49 22
Цитата Сообщение от Deviaphan Посмотреть сообщение
Вот как раз нет. Лучше (с точки зрения эффективности кода) делать это именно ручками. В идеале, оформив в виде класса и inline методами. Битовые поля крайне неэффективны (по крайней мере там было в течении многих веков, возможно это уже не является проблемой для компилятора).
Любой современный компилятор с битовыми полями справится так же, как и с битовыми операциями. Старые компиляторы на intel'е навряд ли дадут выигрыш при работе с битовыми операциями, т.к. получается много промежуточных значений, а регистров мало и всё равно что-то начнёт попадать в стек
0
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
21.10.2012, 12:09 23
Почти ни разу не пользовался битовыми полями, поэтому захотелось сравнить в "полевых" условиях.
Пример специально "запутан", чтобы компилятор не сумел оптимизировать то, чего сравнить хотелось.
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include "stdafx.h"
#include <iostream>
using namespace std;
 
typedef unsigned int Field;
 
struct Color16bitS
{ 
    Field r : 5;
    Field g : 5;
};
 
class Color16bit
{
public:
    void SetR(Field r)
    {
        rgbk &= 0xE0;
        rgbk |= r;
    }
 
    Field GetR() const
    {   return rgbk & 0x1F; }
 
    void SetG(Field g)
    {
        rgbk &= 0xF5EF;
        rgbk |= (g<<5);
    }
 
    Field GetG() const
    {   return (rgbk >> 5) & 0x1F;  }
 
 
    Field rgbk;
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    Field r, g;
    cin >> r >> g;
 
    {
        Color16bitS f;
                
        f.r = r;
        f.g = g;
 
        Field sum = 0;
        if( f.r > 3 )
            sum = f.r + f.g;
        else
        {
            f.r = 0;
        }
 
        cout << sum << " " <<  sizeof(f) << endl;
    }
    
    {
        Color16bit f;
 
        f.SetR(r);
        f.SetG(g);
 
        Field sum = 0;
        if( f.GetR() > 3 )
            sum = f.GetR() + f.GetG();
        else
            f.SetR(0);
 
        cout << sum << " " << sizeof(f) << endl;
    }
 
    cin.get();
    return 0;
}
Оно же (компилятор msvc2010 с оптимизацией по скорости)
Оставил только интересный фрагменты
Assembler
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
47
48
49
50
51
52
53
54
55
56
57
58
59
    mov eax, DWORD PTR _g$[esp+8]
    mov edx, DWORD PTR _f$22438[esp+8]
    mov ecx, DWORD PTR _r$[esp+8]
    and eax, 31                 ; 0000001fH
    shl eax, 5
    and edx, -1024              ; fffffc00H
    and ecx, 31                 ; 0000001fH
    or  eax, edx
    or  eax, ecx
 
; 51   : 
; 52   :        Field sum = 0;
; 53   :        if( f.r > 3 )
 
    mov ecx, eax
    and ecx, 31                 ; 0000001fH
    xor edx, edx
    cmp ecx, 3
    jbe SHORT $LN4@wmain
 
; 54   :            sum = f.r + f.g;
 
    shr eax, 5
    and eax, 31                 ; 0000001fH
    lea edx, DWORD PTR [ecx+eax]
$LN4@wmain:
 
 
 
; 63   :    {
; 64   :        Color16bit f;
; 65   : 
; 66   :        f.SetR(r);
; 67   :        f.SetG(g);
 
    mov eax, DWORD PTR _f$22582[esp+8]
    mov ecx, DWORD PTR _g$[esp+8]
    and eax, 224                ; 000000e0H
    or  eax, DWORD PTR _r$[esp+8]
    shl ecx, 5
    and eax, 62959              ; 0000f5efH
    or  eax, ecx
 
; 68   : 
; 69   :        Field sum = 0;
; 70   :        if( f.GetR() > 3 )
 
    mov ecx, eax
    and ecx, 31                 ; 0000001fH
    xor edx, edx
    cmp ecx, 3
    jbe SHORT $LN2@wmain
 
; 71   :            sum = f.GetR() + f.GetG();
 
    shr eax, 5
    and eax, 31                 ; 0000001fH
    lea edx, DWORD PTR [ecx+eax]
$LN2@wmain:
Получается, что написанный вручную код всего на две операции шустрее битовых полей. Реализовывать структуру полностью мне было лень (там ещё поле для blue и один бит на colorKey должны быть). Похоже, что чем больше полей, тем больше будет выигрыш при написании вручную, но придётся писать вручную. Много. И муторно. Проще забить и использовать битовые поля.
Наименьшее число операций ри использовании типа unisgned int. При использовании int или (unsigned)short число операций возрастает для обоих методов.
В общем, забиваем на всё и используем битовые поля, но только с типом unsigned int.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
21.10.2012, 13:50 24
Я интеловский ассемблер как-то плохо понимаю, а потому вот так глядя на код немного не фтыкаю (надо моск напрягать). С виду по исходнику всё написано правильно и код не должен отличаться. Надо попробовать на свежую голову понять, почему при записи битовых полей код получился длиннее (там немного по математической части кумекать надо, может просто компилятор недостаточно качественно соптимизировал)
0
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
21.10.2012, 14:18 25
Присваивание значений какое-то мутное в битовых полях.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
22.10.2012, 00:11 26
Ничего мутного нет
Расскажите про new и delete в C++
1
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
22.10.2012, 06:03 27
Цитата Сообщение от Evg Посмотреть сообщение
Ничего мутного нет
Так вручную же я те же самые операции делаю: считывание "подложки", обнуление соответствующих битов, сдвиг и добавление.

А в чём разница до меня дошло! Вручную я не проверял, что вводимое значение на корректность (размер в битах), а битовые поля проверку выполняют (and ecx, 31), на всякий случай обнуляя лишние биты. Если добавить код проверки в класс Color16bit, то вообще никакой разницы не будет между ручной реализацией и битовым полем. Так что забываю про то, что битовые поля не эффективные.

Добавлено через 1 минуту
Цитата Сообщение от Deviaphan Посмотреть сообщение
до меня дошло!
А щяс и комментарий в твоей ссылке прочитал и дважды дошло.)
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
22.10.2012, 08:50 28
Цитата Сообщение от Deviaphan Посмотреть сообщение
Вручную я не проверял, что вводимое значение на корректность
Да, проморгал я этот момент....

Цитата Сообщение от Deviaphan Посмотреть сообщение
Так что забываю про то, что битовые поля не эффективные
Единственная их неэффективность могла бы заключаться в том, что структуру компилятор чаще загоняет в стек, чем скалярное значение. В современных компиляторах это пофигу, а вот в старых в этом месте действительно могла просочиться неэффективность.

А что касается чтения/записи полей, то на некоторых процессорах (где-то видел, но не помню, где именно) есть специальные операции для этого дела. Теоретически компилятор может и битовую арифметику к этим операциям свести, но практически надо проверять
0
22.10.2012, 08:50
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.10.2012, 08:50
Помогаю со студенческими работами здесь

Является ли оператор sizeof синтаксическим сахаром над System.Runtime.InteropServices.Marshal.SizeOf?
Является ли оператор sizeof синтаксическим сахаром над...

Что обозначает строка вида sizeof(data)/sizeof(data[0])?
#include &quot;stdafx.h&quot; #include &lt;stdio.h&gt; void bubble_sort(float *data, int size) { int i,j; ...

Marshal.SizeOf и sizeof
чем отличаются Marshal.SizeOf и sizeof? я просто почему то привык пользоваться Marshal.SizeOf, так...

Задача на битовую магию
Развлекался с модулем АЦП в одной STM-ке и наткнулся на интересную задачу. Сама задача к...


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

Или воспользуйтесь поиском по форуму:
28
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru