LINUX.ORG.RU

Запись структуры в файл


0

1

При переписывании простенькой программы с виндовского Microfoft Visual C++ к съедобному для GCC виду, обнаружил следующее. Есть некоторая структура, размером 14 байт. В памяти она округляется до 16. При записи в файл записываются 16, при чем два байта мусора появляются именно в середине. Кусок кода:

#include<stdio.h>

typedef unsigned char BYTE;
typedef unsigned short int WORD;
typedef unsigned int  DWORD;
typedef long int LONG;


typedef struct tagBITMAPFILEHEADER {
  WORD  bfType;
  DWORD bfSize;
  WORD  bfReserved1;
  WORD  bfReserved2;
  DWORD bfOffBits;
} BITMAPFILEHEADER;


void main(int argc,char **argv)
{
BITMAPFILEHEADER header;

header.bfType=0;
header.bfSize=0;
header.bfReserved1=0;
header.bfReserved2=0;
header.bfOffBits=0;

FILE *t;

t=fopen("tst","wb");
fwrite(&header,sizeof(header),1,t);
fclose(t);

return;
}
Вместо ожидаемого
0000 00000000 0000 0000 00000000
Я вижу следующее
0000 4EED 00000000 0000 0000 00000000
Была идея добавить в конец еще один пустой WORD, а после записи структуры перемещаться на 2 байта ближе к началу, но это костыли. Как правильно решить проблемму?

Ответ на: комментарий от hateyoufeel

__attribute__((pack))

packed же. Это в MSVC #pragma pack

typedef struct __attribute__((__packed__)) tagBITMAPFILEHEADER {
  WORD  bfType;
  DWORD bfSize;
  WORD  bfReserved1;
  WORD  bfReserved2;
  DWORD bfOffBits;
} BITMAPFILEHEADER;

i-rinat ★★★★★ ()

Проблема — в выравнивании членов структуры для ускорения доступа к ним. Если читаться структура будет той же самой программой, а лишнее занимаемое не критично, можно оставить как есть. В противном случае делается так:

#pragma pack(push,1)
struct on_byte_aligned {
...
};
#pragma pack(pop)

Теперь структура будет записываться в файл «как надо», но при этом скорость её обработки в программе может снизиться.

uuwaan ★★ ()
Ответ на: комментарий от i-rinat

packed же. Это в MSVC #pragma pack

gcc тоже прагму понимает спокойно.

uuwaan ★★ ()

http://ru.wikipedia.org/wiki/Выравнивание_данных

Решение - парсить/сериализовывать побайтно, возможно, используя для этого какую-нибудь готовую библиотеку. А за дампы структуры в приличном обществе принято гонять канделябром.

Minoru ★★★ ()

Найди какую нибудь библиотеку для сериализации и заюзай её.

invy ★★★★★ ()
Ответ на: комментарий от Minoru

А за дампы структуры в приличном обществе принято гонять канделябром.

Судя по его typedef'ам, у него всё равно код только под x86. Так что особой разницы, наверное, нет. Разве что может возникнуть проблема безопасности, если не быть аккуратным.

proud_anon ★★★★★ ()
Ответ на: комментарий от Minoru

Решение - парсить/сериализовывать побайтно, возможно, используя для этого какую-нибудь готовую библиотеку.

Лорчую. И это единственный переносимый способ, поскольку на разных архитектурах могут отличаться не только выравнивания, но и порядок байт, и даже длина байта. А все эти «unpacked» — писишный костыль.

alegz ★★ ()
Ответ на: комментарий от Minoru

Решение - парсить/сериализовывать побайтно

Не побайтно, а по полям.

anonymous ()
Ответ на: комментарий от anonymous

Спасибо тебе, аноним. Довольно необычное ощущение — увидеть свой комментарий полуторалетней давности в казалось бы свежей теме.

i-rinat ★★★★★ ()
Ответ на: комментарий от alegz

Можно увидеть, уважаемый эксперт, ваши поделки, которые работают(именно работают) за рамками «писишки»? Твои лабы на аврке меня мало волнуют - именно на архитектурах калибра «писишки». Я жду.

«работают» - это действительно работают и лично у тебя. Т.е. показываешь мне твою «не писишку» вместо со своим способом. А чтобы окончательно тебя добить ты мне показываешь другую длину байт(у тебя лично) и другое выравнивание, так же у тебя лично.

registrant27492 ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.