Проблема с sizeof
От: shabshay  
Дата: 12.04.02 05:24
Оценка:
Есть такой код:
    struct s{
        byte b1;
        byte b2;
        int i1;
        byte b3;
    };

    s var;
    DWORD dw1 = sizeof (var);
    
    DWORD dw2 = sizeof (var.b1) + sizeof (var.b2) + 
        sizeof (var.i1) + sizeof (var.b3);

Результат:
dw1 = 12
dw2 = 7

Как это может быть?
Re: Проблема с sizeof
От: Кирпа В.А. Украина  
Дата: 12.04.02 05:27
Оценка:
Здравствуйте shabshay, Вы писали:

S>Есть такой код:

S>
S>    struct s{
S>        byte b1;
S>        byte b2;
S>        int i1;
S>        byte b3;
S>    };

S>    s var;
S>    DWORD dw1 = sizeof (var);
S>    
S>    DWORD dw2 = sizeof (var.b1) + sizeof (var.b2) + 
S>        sizeof (var.i1) + sizeof (var.b3);
S>

S>Результат:
S>dw1 = 12
S>dw2 = 7
S>
S>Как это может быть?

Пробленма с выравниванием структур
Поставь выравнивание на 1 байт и dw1 станет равным dw2
!0xDEAD
Re: Проблема с sizeof
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 12.04.02 05:29
Оценка: 2 (1)
Здравствуйте shabshay, Вы писали:


Потому что компилятор выровнял каждое поле на 4 байта, если тебе надо чтобы не было промежутков,
пиши так:

#pragma pack (push, 1) //следущий код выравнивать на 1 байт
struct s
{
  byte b1;
  byte b2;
  int i1;
  byte b3;
};
#pragma pack (pop) //восстановить исходную паковку


pragma-ы приведены для VC, для другого компилятора они могут быть другими
Re[2]: Проблема с sizeof
От: shabshay  
Дата: 12.04.02 06:14
Оценка:
Здравствуйте DarkGray, Вы писали:
DG>Потому что компилятор выровнял каждое поле на 4 байта, если тебе надо чтобы не было промежутков,
DG>пиши так:

DG>
DG>#pragma pack (push, 1) //следущий код выравнивать на 1 байт
DG>struct s
DG>{
DG>  byte b1;
DG>  byte b2;
DG>  int i1;
DG>  byte b3;
DG>};
DG>#pragma pack (pop) //восстановить исходную паковку
DG>


DG>pragma-ы приведены для VC, для другого компилятора они могут быть другими



Работает , но непонял почему , объясни для тех кто на бронепоезде и с первого раза не въежжает.
На ATL тоже самое?
Re[3]: Проблема с sizeof
От: Micker  
Дата: 12.04.02 06:24
Оценка:
Здравствуйте shabshay, Вы писали:

S>

S>Работает , но непонял почему , объясни для тех кто на бронепоезде и с первого раза не въежжает.
S>На ATL тоже самое?

Компилятор имеет своийство выравнивать структуры — то есть распологать члены структуры по адресам, кратным 2, 4, 8 и т.д. байт. Это делается для того, что бы ускорить процесс доступа к этим членам (машине по таким адресам лазить). Для этого между членами структуры компилятор отавляет неиспользуемое пространство памяти.
Когда же ты выравниваешь на 1, то компилятор ни чего не выравнивает, а оставляет всё как есть.
Жизнь, как игра —
идея паршивая,
графика обалденная...
Re[4]: Проблема с sizeof
От: shabshay  
Дата: 12.04.02 06:35
Оценка:
Здравствуйте Micker, Вы писали:

M>Компилятор имеет своийство выравнивать структуры — то есть распологать члены структуры по адресам, кратным 2, 4, 8 и т.д. байт. Это делается для того, что бы ускорить процесс доступа к этим членам (машине по таким адресам лазить). Для этого между членами структуры компилятор отавляет неиспользуемое пространство памяти.

M>Когда же ты выравниваешь на 1, то компилятор ни чего не выравнивает, а оставляет всё как есть.

Re[4]: Проблема с sizeof
От: Кодт Россия  
Дата: 12.04.02 06:42
Оценка: 36 (4)
Здравствуйте Micker, Вы писали:

S>>Работает , но непонял почему , объясни для тех кто на бронепоезде и с первого раза не въежжает.


struct s { BYTE b1; BYTE b2; DWORD dw3; BYTE b4; };

+-------------------+-------------------+-------------------+
+----+----+----+----+----+----+----+----+----+----+----+----+
| b1 | b2 |    |    | <------dw3------> | b4 |    |    |    |  -- sizeof(s)==12
+----+----+----+----+----+----+----+----+----+----+----+----+
          |-------->                         |------------->
                  выравнивание до границы слова

struct p { BYTE b1; BYTE b2; BYTE b3; DWORD dw4; };

+-------------------+-------------------+
+----+----+----+----+----+----+----+----+
| b1 | b2 | b3 |    | <------dw4------> |  -- sizeof(p)==8
+----+----+----+----+----+----+----+----+
               |--->
               выравнивание до границы слова

pragma pack(push,1);

+-------------------+-------------------+
+----+----+----+----+----+----+----+
| b1 | b2 | <------dw3------> | b4 |    -- sizeof(s)==7
+----+----+----+----+----+----+----+
+----+----+----+----+----+----+----+
| b1 | b2 | b3 | <------dw4------> |    -- sizeof(p)==7
+----+----+----+----+----+----+----+
Перекуём баги на фичи!
Re[5]: Проблема с sizeof
От: shabshay  
Дата: 12.04.02 06:54
Оценка:
Здравствуйте Кодт, Вы писали:

К>Здравствуйте Micker, Вы писали:


S>>>Работает , но непонял почему , объясни для тех кто на бронепоезде и с первого раза не въежжает.


К>
К>struct s { BYTE b1; BYTE b2; DWORD dw3; BYTE b4; };

К>+-------------------+-------------------+-------------------+
К>+----+----+----+----+----+----+----+----+----+----+----+----+
К>| b1 | b2 |    |    | <------dw3------> | b4 |    |    |    |  -- sizeof(s)==12
К>+----+----+----+----+----+----+----+----+----+----+----+----+
К>          |-------->                         |------------->
К>                  выравнивание до границы слова

К>struct p { BYTE b1; BYTE b2; BYTE b3; DWORD dw4; };

К>+-------------------+-------------------+
К>+----+----+----+----+----+----+----+----+
К>| b1 | b2 | b3 |    | <------dw4------> |  -- sizeof(p)==8
К>+----+----+----+----+----+----+----+----+
К>               |--->
К>               выравнивание до границы слова

К>pragma pack(push,1);

К>+-------------------+-------------------+
К>+----+----+----+----+----+----+----+
К>| b1 | b2 | <------dw3------> | b4 |    -- sizeof(s)==7
К>+----+----+----+----+----+----+----+
К>+----+----+----+----+----+----+----+
К>| b1 | b2 | b3 | <------dw4------> |    -- sizeof(p)==7
К>+----+----+----+----+----+----+----+

К>

Re: Еще проблема с sizeof
От: Vi2 Удмуртия http://www.adem.ru
Дата: 15.04.02 10:47
Оценка:
    struct sClass
    { // Это может быть и class с публичным доступом, не только struct
        // ...
        int iValue;
        // ...
    };
// ...
    size_t sLen = sizeof( sClass::iValue );

Последний оператор компилится с ошибкой:
C:\Projects\test\test.cpp(21) : error C2070: illegal sizeof operand

Почему?
У меня переменных этого класса нет, поэтому получилось через указатель NULL:
    size_t sLen = sizeof( ((sClass*)NULL)->iValue );

Но не извращение ли это? По имени — не может, а через фиктивный указатель — пожалуйста!
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: Еще проблема с sizeof
От: Zero  
Дата: 15.04.02 11:32
Оценка:
Здравствуйте Vi2, Вы писали:

Vi2>
Vi2>    struct sClass
Vi2>    { // Это может быть и class с публичным доступом, не только struct
Vi2>        // ...
Vi2>        int iValue;
Vi2>        // ...
Vi2>    };
Vi2>// ...
Vi2>    size_t sLen = sizeof( sClass::iValue );
Vi2>

Vi2>Последний оператор компилится с ошибкой:
Vi2>C:\Projects\test\test.cpp(21) : error C2070: illegal sizeof operand

Vi2>Почему?

Vi2>У меня переменных этого класса нет, поэтому получилось через указатель NULL:
Vi2>
Vi2>    size_t sLen = sizeof( ((sClass*)NULL)->iValue );
Vi2>

Vi2>Но не извращение ли это? По имени — не может, а через фиктивный указатель — пожалуйста!

Потому и выдаёт ошибку, что экземпляра нет. Нельзя использовать нестатические
члены класса в выражениях ClassName::MemberName.
Re[6]: Проблема с sizeof
От: KonstantinA Россия  
Дата: 16.04.02 15:52
Оценка:
Здравствуйте shabshay, Вы писали:

S>Здравствуйте Кодт, Вы писали:


К>>Здравствуйте Micker, Вы писали:


S>>>>Работает :up: , но непонял почему :( , объясни для тех кто на бронепоезде и с первого раза не въежжает.


К>>
К>>struct s { BYTE b1; BYTE b2; DWORD dw3; BYTE b4; };

К>>+-------------------+-------------------+-------------------+
К>>+----+----+----+----+----+----+----+----+----+----+----+----+
К>>| b1 | b2 |    |    | <------dw3------> | b4 |    |    |    |  -- sizeof(s)==12
К>>+----+----+----+----+----+----+----+----+----+----+----+----+
К>>          |-------->                         |------------->
К>>                  выравнивание до границы слова

К>>struct p { BYTE b1; BYTE b2; BYTE b3; DWORD dw4; };

К>>+-------------------+-------------------+
К>>+----+----+----+----+----+----+----+----+
К>>| b1 | b2 | b3 |    | <------dw4------> |  -- sizeof(p)==8
К>>+----+----+----+----+----+----+----+----+
К>>               |--->
К>>               выравнивание до границы слова

К>>pragma pack(push,1);

К>>+-------------------+-------------------+
К>>+----+----+----+----+----+----+----+
К>>| b1 | b2 | <------dw3------> | b4 |    -- sizeof(s)==7
К>>+----+----+----+----+----+----+----+
К>>+----+----+----+----+----+----+----+
К>>| b1 | b2 | b3 | <------dw4------> |    -- sizeof(p)==7
К>>+----+----+----+----+----+----+----+

К>>

S> :super:

Вообще говоря, самый приличный вариант { DWORD, BYTE, BYTE, BYTE } (7). Все типы выровнены.
Т.к. доступ к невыровненным данным ( т.е. адрес не кратен размеру типа )
занимает больше времени. Рихтер пишет что-то типа,
что процессор x86 это делает сам (раз в 20 дольше чем для выровненного типа ),
а процессоры Alpha генерят исключения, которые обрабатывает OS ( в 1000-2000 раз медленнее ).
Более того можно (не помню как, см. Рихтер ) сделать чтобы исключение генерилось
и для x86.
Re[3]: Еще проблема с sizeof
От: Андрей Тарасевич Беларусь  
Дата: 16.04.02 16:00
Оценка:
Здравствуйте Zero, Вы писали:

Z>Потому и выдаёт ошибку, что экземпляра нет. Нельзя использовать нестатические

Z>члены класса в выражениях ClassName::MemberName.

Зависит от контекста. На территории метода класса 'ClassName' или его потомка можно ссылаться на нестатические члены класса именами вида 'ClassName::MemberName'.
Best regards,
Андрей Тарасевич
Re[7]: Проблема с sizeof
От: KonstantinA Россия  
Дата: 16.04.02 17:28
Оценка: 3 (1)
Здравствуйте KonstantinA, Вы писали:

KA>Вообще говоря, самый приличный вариант { DWORD, BYTE, BYTE, BYTE } (7). Все типы выровнены.

KA>Т.к. доступ к невыровненным данным ( т.е. адрес не кратен размеру типа )
KA>занимает больше времени. Рихтер пишет что-то типа,
KA>что процессор x86 это делает сам (раз в 20 дольше чем для выровненного типа ),
KA>а процессоры Alpha генерят исключения, которые обрабатывает OS ( в 1000-2000 раз медленнее ).
KA>Более того можно (не помню как, см. Рихтер ) сделать чтобы исключение генерилось
KA>и для x86. :down:

Извиняюсь за допущенные неточности:
1.Рихтер не говорит насколько велико замедление на x86.Не менее чем в 2 раза.
2. на Alpha замедление доходит до порога в 100 раз
3. на x86 Windows 2000(98) не меняют флаг процессора ответственны за генерацию исключений из-за невыровненных данных. Поэтому там процессор справляется сам.
4. на Alpha можно поменять флажок в реестре, чтобы система не обрабатывала исключения о невыровненных данных. Тогда программа аварийно завершиться.
5. можно смотреть частоту ошибок выравнивания через perfmon.
6. размер структуры {DWORD,BYTE,BYTE,BYTE} без всяких извращений все-таки 8 байт. Но мне как-то не жалко здесь 1-го байта
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.