Re: sizeof(...)
От: stealth296 Великобритания  
Дата: 04.08.04 04:58
Оценка:
Здравствуйте, Saydex, Вы писали:

S>Вот такой код:


S>
S>typedef float Vector[3];
S>typedef float Texel[2];
S>typedef float Matrix[4][4];
S>typedef int Bool;
S>typedef unsigned char Byte;
S>typedef unsigned short int Word;
S>typedef unsigned long Dword;
S>typedef float Float;

S>typedef struct _BoxMap {
S>    char front[64];
S>    char back[64];
S>    char left[64];
S>    char right[64];
S>    char top[64];
S>    char bottom[64];
S>}BoxMap;

S>typedef struct _MapData {
S>    Word maptype;
S>    Vector pos;
S>    Matrix matrix;
S>    Float scale;
S>    Float tile[2];
S>    Float planar_size[2];
S>    Float cylinder_height;
S>}MapData;

S>typedef struct _Mesh3 {
S>    Matrix matrix;
S>    Dword points;
S>    Dword flags;
S>    Dword texels;
S>    Dword faces;
S>    BoxMap box_map;
S>    MapData map_data;
S>}Mesh3;

S>typedef struct _Mesh4 {
S>    Byte color;
S>    Matrix matrix;
S>    Dword points;
S>    Dword flags;
S>    Dword texels;
S>    Dword faces;
S>    BoxMap box_map;
S>    MapData map_data;
S>}Mesh4;

S>DWORD sm3 = sizeof(Mesh3);
S>DWORD sm4 = sizeof(Mesh4);
S>


S>Так вот sm3 = 568, а sm4 = 572. Но как это получается? Ведь sizeof(Byte) = 1 !


S>У меня стоит Visual C++ 6.0. Что мне делать? Именно из-за этого я не могу сделать так:

S>WriteFile(hFile,&mesh4,sizeof(Mesh4),&dw,0). Ведь оно запишется неправильно! Как быть?

Придётся вам познакомиться с термином "выравнивание". Дело в том, что размер той или иной структуры не всегда равен размеру её членов. Существуют правила, в соответствии с которыми члены структур должны выравниваться по границе блоков определённого размера. Это необходимо для ускорения доступа к отдельным членам структур (оптимизации) или для достижения соответствия требованиям к памяти в той или иной реализации. Как было сказано выше, члены структур должны быть выравнены по определённой (числом байт!) границе, размеры которой можно регулировать при помощи директивы #pragma pack([push | pop], [size_of_bytes n]).

Я слегка модифицировал ваш код для выравнивания по границе 8 байт (здесь показана лишь та часть кода, которая была подвержена модификации):

#pragma pack(push, 8)

typedef struct _MapData {
    Matrix matrix;
    Vector pos;
    unsigned int : 4;
    Float tile[2];
    Float planar_size[2];
    Float scale;
    Float cylinder_height;
    unsigned int : 7;
    Word maptype;
}MapData;

typedef struct _Mesh3 {
    BoxMap box_map;
    MapData map_data;
    Matrix matrix;
    Dword points;
    Dword flags;
    Dword texels;
    Dword faces;
}Mesh3;

typedef struct _Mesh4 {
    BoxMap box_map;
    MapData map_data;
    Matrix matrix;
    Dword points;
    Dword flags;
    Dword texels;
    Dword faces;
    unsigned int : 7;
    Byte color;
}Mesh4;

#pragma pack(pop)

DWORD sm3 = sizeof(Mesh3);
DWORD sm4 = sizeof(Mesh4);


А вот результаты расчётов:

BoxMap — 64*6 = 384
MapData — 64+12+4+8+8+4+4+7+1 = 112 (кратное 8)

Mesh3 — 384+112+64+4+4+4+4 = 576
Mesh4 — 384+112+64+4+4+4+4+7+1 = 584

Битовые поля (bit fields) помогают выравнять члены структур по границам байт.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.