Структура упаковки двуличность

Я пишу код для спецификация который определяет структуры без упаковки, например:

struct LASHeader_1p2
{
char FileSig[4]; //= "LASF";                    // 4
unsigned __int16 FileSource;                    // 2   6
unsigned __int16 Reserved_Unused;               // 2   8
unsigned __int32 Project_ID_Data1;              // 4  12
unsigned __int16 Project_ID_Data2;              // 2  14
unsigned __int16 Project_ID_Data3;              // 2  16
char Project_ID_Data4[8];                       // 8  24
unsigned char Version_Major;                    // 1  25
unsigned char Version_Minor;                    // 1  26
char System_ID[32];                             //32  58
char Software[32];                              //32  90
unsigned __int16 FC_Day, FC_Year, Header_Size;  // 2,2,2 96
unsigned __int32 Offset_to_Data;                // 4 100 0x60
unsigned __int32 VarLenRecs;                    // 4 104 0x64
unsigned char Pt_DataFormat;                    // 1 105 0x65
unsigned __int16 Pt_DataRecLen;                 // 2 107 0x68
unsigned __int32 PointCount;                    // 4 111 0x6A
unsigned __int32 Point_by_Return_0;             // 4 115
unsigned __int32 Point_by_Return_1;             // 4 119
unsigned __int32 Point_by_Return_2;             // 4 123
unsigned __int32 Point_by_Return_3;             // 4 127
unsigned __int32 Point_by_Return_4;             // 4 131
double Xscale;                                  // 8 139
double Yscale;                                  // 8 147
double Zscale;                                  // 8 155
double Xoffset;                                 // 8 163
double Yoffset;                                 // 8 171
double Zoffset;                                 // 8 179
double MaxX;                                    // 8 187
double MinX;                                    // 8 195
double MaxY;                                    // 8 203
double MinY;                                    // 8 211
double MaxZ;                                    // 8 219
double MinZ;                                    // 8 227
};

Вокруг unsigned char Pt_DataFormat; структура выходит из выравнивания по умолчанию (4 байта). Чтобы компенсировать это, я использую опцию компилятора / Zp1, чтобы использовать структуру без дополнения / выравнивания. Хотя потенциально медленнее, это позволяет мне читать байты и интерпретировать их как структуру:

char* buffer = (char*)malloc(sizeof(LASHeader_1p2));
pReadStream.read(buffer ,sizeof(LASHeader_1p2));
LASHeader_1p2* Header = (LASHeader_1p2*)buffer;

Который я могу изменить значения, а затем записать в файл в виде байтов. Единственный другой вариант — разбить структуру на разделы, которые выровняют и прочтут этот отдельный байт, что мне кажется несколько странным.

Однако другие библиотеки не любят / Zp1, я подозреваю, что они содержат структуры с внутренним дополнением, которые больше не работают, когда не дополнены.

Я смотрел на прагма пакет а также __declspec (выравнивание ()) но я не уверен, какой из них подходит и как их использовать.

Может ли кто-нибудь пролить свет на то, как действовать дальше: читать и приводить структуру без заполнения, но поддерживать заполнение для других библиотек, которым это требуется?

0

Решение

Для Visual Studio вы хотели бы окружить вашу структуру:

#pragma pack(push, 1) //Save packing value and set to 1 byte
<struct definition>
#pragma pack(pop)  //Reset to whatever the packing was before.

Итак, это:

#include <iostream>

#pragma pack(push, 1)
struct packed
{
char FileSig[4]; //= "LASF";                    // 4
unsigned __int16 FileSource;                    // 2   6
unsigned __int16 Reserved_Unused;               // 2   8
unsigned __int32 Project_ID_Data1;              // 4  12
unsigned __int16 Project_ID_Data2;              // 2  14
unsigned __int16 Project_ID_Data3;              // 2  16
char Project_ID_Data4[8];                       // 8  24
unsigned char Version_Major;                    // 1  25
unsigned char Version_Minor;                    // 1  26
char System_ID[32];                             //32  58
char Software[32];                              //32  90
unsigned __int16 FC_Day, FC_Year, Header_Size;  // 2,2,2 96
unsigned __int32 Offset_to_Data;                // 4 100 0x60
unsigned __int32 VarLenRecs;                    // 4 104 0x64
unsigned char Pt_DataFormat;                    // 1 105 0x65
unsigned __int16 Pt_DataRecLen;                 // 2 107 0x68
unsigned __int32 PointCount;                    // 4 111 0x6A
unsigned __int32 Point_by_Return_0;             // 4 115
unsigned __int32 Point_by_Return_1;             // 4 119
unsigned __int32 Point_by_Return_2;             // 4 123
unsigned __int32 Point_by_Return_3;             // 4 127
unsigned __int32 Point_by_Return_4;             // 4 131
double Xscale;                                  // 8 139
double Yscale;                                  // 8 147
double Zscale;                                  // 8 155
double Xoffset;                                 // 8 163
double Yoffset;                                 // 8 171
double Zoffset;                                 // 8 179
double MaxX;                                    // 8 187
double MinX;                                    // 8 195
double MaxY;                                    // 8 203
double MinY;                                    // 8 211
double MaxZ;                                    // 8 219
double MinZ;                                    // 8 227
};
#pragma pack(pop)

struct unpacked
{
char FileSig[4]; //= "LASF";                    // 4
unsigned __int16 FileSource;                    // 2   6
unsigned __int16 Reserved_Unused;               // 2   8
unsigned __int32 Project_ID_Data1;              // 4  12
unsigned __int16 Project_ID_Data2;              // 2  14
unsigned __int16 Project_ID_Data3;              // 2  16
char Project_ID_Data4[8];                       // 8  24
unsigned char Version_Major;                    // 1  25
unsigned char Version_Minor;                    // 1  26
char System_ID[32];                             //32  58
char Software[32];                              //32  90
unsigned __int16 FC_Day, FC_Year, Header_Size;  // 2,2,2 96
unsigned __int32 Offset_to_Data;                // 4 100 0x60
unsigned __int32 VarLenRecs;                    // 4 104 0x64
unsigned char Pt_DataFormat;                    // 1 105 0x65
unsigned __int16 Pt_DataRecLen;                 // 2 107 0x68
unsigned __int32 PointCount;                    // 4 111 0x6A
unsigned __int32 Point_by_Return_0;             // 4 115
unsigned __int32 Point_by_Return_1;             // 4 119
unsigned __int32 Point_by_Return_2;             // 4 123
unsigned __int32 Point_by_Return_3;             // 4 127
unsigned __int32 Point_by_Return_4;             // 4 131
double Xscale;                                  // 8 139
double Yscale;                                  // 8 147
double Zscale;                                  // 8 155
double Xoffset;                                 // 8 163
double Yoffset;                                 // 8 171
double Zoffset;                                 // 8 179
double MaxX;                                    // 8 187
double MinX;                                    // 8 195
double MaxY;                                    // 8 203
double MinY;                                    // 8 211
double MaxZ;                                    // 8 219
double MinZ;                                    // 8 227
};int main()
{
std::cout << "sizeof(packed)   = " << sizeof(packed) << "\n";
std::cout << "sizeof(unpacked) = " << sizeof(unpacked) << "\n";
return 0;
}

выходы

sizeof(packed)   = 227
sizeof(unpacked) = 232

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

1

Другие решения


По вопросам рекламы [email protected]