LINUX.ORG.RU

Ламерский вопрос по структурам и sizeof


0

0

Есть такая вот структура:

struct tagBMPFileHeader
{
short int bfType;
int bfSize;
short int bfReserved1;
short int bfReserved2;
int bfOffBits;
};


Почему sizeof(tagBMPFileHeader) == 16 ?
Если убрать к примеру short int bfType
sizeof становится равен 12.
Это как ?
Выравнивание что ли?
И как от этого избавится, т. к. из файла структуру читает неправильно:
fread(&BMPFileHeader, sizeof(BMPFileHeader), 1, f);
выдаёт информацию со "сдвигом" на 2 байта вправо.

Компилятор gcc 2.96


> Выравнивание что ли?

Оно!

> И как от этого избавится ...

Никак!

> т. к. из файла структуру читает неправильно:

Много тут было сказано про тех, кто пишет структуры в файлы, незлых тихих слов...

Есть такая штука, называется "сериализация". Впрочем, не надо получать высшее образование для того, чтобы догадаться, как спасти в файл/прочитать обратно несколько целых чисел...

Die-Hard ★★★★★
()

struct packetHeader {
/** bla-bla-bla **/
} __attribute__((packed));

кажись так..давно не писал упакованных структур ;-)

p.s. уже как-то говорил на этом форуме - читайте блин документацию..
а то развелось понимаешь писателей ;-)


MKuznetsov ★★★★★
()
Ответ на: комментарий от Die-Hard

Die-Hard : Вам тоже нелишне почитать man`ы

а легенду о сериализации раскажите по осмыслению прочитанного ;-) и не надо давать заведомо ложных ответов

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

MKuznetsov :

> __attribute__((packed));

Угу, я еще есть масса замечательных прагм!

За подобные приемы в приличном обществе полагается 10 лет расстрела вонючими пулями! :)

Die-Hard ★★★★★
()
Ответ на: комментарий от MKuznetsov

2MKuznetsov:

> и не надо давать заведомо ложных ответов

Не понял ....

Если Вас не затруднит, не могли бы Вы, любезнейший, пролить свет Вашей мудрости на недостойного глупца, не способного осмыслить Великие Маны? :-)

З.Ы.

Впрочем, подозреваю, Ваши сведения о сериализации исчерпываются курсом лекций какого-нибудь Великого Профессора какого-нибудь Государственного Бобруйского Университета ;)

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

ну точно писатель :-)

потрудитесь ещё раз прочесть тему топика

ЦИТАТА ИЗ ТЕМЫ:

Выравнивание что ли?
И как от этого избавится, т. к. из файла структуру читает неправильно:
fread(&BMPFileHeader, sizeof(BMPFileHeader), 1, f);
выдаёт информацию со "сдвигом" на 2 байта вправо.

ВАШ ОТВЕТ : никак

и многоумные мысли про сериализацию данных.. 

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

MKuznetsov (18.10.2005 0:30:14):

> ну точно писатель :-)

Понятно. Теоретик :-)

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

>За подобные приемы в приличном обществе полагается 10 лет расстрела вонючими пулями!

Не потрудитесь запустить grep -r '__attribute__' /usr/src/linux-x.y.z :-) Весь lkml уложим в яму... или вонючих пуль не хватит. Может проще разрешить им пользовать __attribute__? :-)

logIN
()
Ответ на: комментарий от Die-Hard

Вдогонку:

Автору топика:

Конечно, __attribute__((packed))сработает на _конкретном_ gcc_ на _конкретном_ компьютере. Если это все, что тебе надо, то можешь юзать. Но тогда ССЗБ -- не удивляйся, когда все это вдруг в один прекрасный момент начнет глючить.

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

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

>спасать/читать данные чуть более переносимым способом.

Как? Вот например в tcp/ip используют структуры, но "правильные", без возможности таких вот сдвигов. Какой еще способ, кроме создания псевдо-структур (просто писать в файл подобие s.a = "...", s.b = "...", потом все читать обратно) можно предложить?

logIN
()
Ответ на: комментарий от Die-Hard

>Ну, попробуйте собрать /usr/src/linux-x.y.z чем-то, отличным от gcc требуемой версии

Давно видел, что как-то c помощью icc собрали. Или приснилось?
Мало того, средства для выравнивания существуют в любом компиляторе. Портируемость можно обеспечить define'ами.

logIN
()
Ответ на: комментарий от Die-Hard

Да мне надо-то картинку одну BMP шную 700меговую чуть-чуть преобразовать. ImageMagick спасовал, вот я и решил сам написать нужный мне одноразовый конвертер. А тут вдруг такое уже при чтении заголовка :)
Я конечно решил, читая каждое поле по-отдельности, но блин интересно же всё-таки :)

Спасибо всем, буду курить огромную такую чёрную книгу по GCC Артура Гриффитса :)

ksicom
() автор топика
Ответ на: комментарий от logIN

> Давно видел, что как-то c помощью icc собрали. Или приснилось?

1. icc специально заточен под совместимость с gcc.

2. сборки ядра icc были экспериментальными. Сырцы патчились (довольно неслабо) и работало все весьма условно.

> Портируемость можно обеспечить define'ами.

Вот за такой подход я и предлагал суровое наказание :)

(Разумеется, если речь идет о ядре, то так и делают, но для спасения данных юзерландовскими аппликухами в 99% это моветон.)

Die-Hard ★★★★★
()
Ответ на: комментарий от logIN

logIN (18.10.2005 0:44:37)Ж

> Какой еще способ, кроме создания псевдо-структур (просто писать в файл подобие s.a = "...", s.b = "...", потом все читать обратно) можно предложить?

Собственно, никакого...

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

>1. icc специально заточен под совместимость с gcc

Ну разве это не радает? ;-)

>Вот за такой подход я и предлагал суровое наказание :)

Эх. В реальной жизни всякое надо применять. Может и не очень красивое, зависит от ситуации. Ресстреливать надо тех, кто придумывает вот такие сдвинутые структуры. ;-)

>но для спасения данных юзерландовскими аппликухами в 99% это моветон

Можно пример из жизни, когда для юзерлэнда это не сработает?

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

> Можно пример из жизни, когда для юзерлэнда это не сработает?

Это многократно обсуждалось.

Везде, где можно, следует избегать писать в файлы "голые" структуры. "Rule of thumb". Один из наиболее мешающих жить источников несовместимостей.

Die-Hard ★★★★★
()
Ответ на: комментарий от ksicom

Кстати о портируемости... ksicom, для структур крайне не советую использовать int/short/итп. Есть стандартные POSIX типы [u]int{8,16,32,64}_t. Например uint32_t. u_int_{8,16...} - устаревшие BSD типы, лучше не использовать.

logIN
()
Ответ на: комментарий от Die-Hard

>Это многократно обсуждалось

Ладно, поищу. Но, лично я, навскидку не могу придумать (если создавать правильные структуры).
Кстати, уверен, что в базах данных используют структуры напрямую. Объяснение простое: довольно накладно парсить такой вот портируемый формат хранения структур.

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

logIN

> ...для структур крайне не советую использовать int/short/итп. Есть стандартные POSIX типы [u]int{8,16,32,64}_t. Например uint32_t. u_int_{8,16...} - устаревшие BSD типы, лучше не использовать.

Категорически не согласен!

То есть, наоборот. "стандартные POSIX типы [u]int{8,16,32,64}_t" -- недавний с99 стандарт (POSIX'ов всяких много!), который не понимают _большинство_ из существующих компиляторов.

А "int/short/итп" понимают все (хотя и не однозначно, в отличие от u]int{8,16,32,64}_t. :( )

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

>Категорически не согласен! То есть, наоборот.

Так согласен или нет? :-)

Будет странно если и не согласен, и одновременно ратуешь за портируемость.

logIN
()
Ответ на: комментарий от Die-Hard

кстати, " _большинство_ из существующих компиляторов" - это VisualC ?

честно говоря, не знаю как у них с поддержкой стандартов, но <stdint.h> из С99 должен быть..это-ж поддержка на уровне библиотеки.

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

>это-ж поддержка на уровне библиотеки

Ага. Да и никто не мешает, в случае криворукости компилятора, сделать typedef'ы самому.

logIN
()

Подумал тут... сейчас придет nsav-ng и скажет как ему нас жалко, мол лисп рулит. ;-)

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

logIN : (просто к сведению) при передаче по сети (в верхних протоколах) для однозначного кодирования/декодирования сложных структур используются BER,DER,XDR кодирование, принцип достатчно прост : поля предваряются тегами в которых содежится инфа о типе,теге и (по необходимости) о длинне. Цифровые данные представляются в естественном порядке битов, текстовые в заранее оговорённой кодировке (как правило в unicode), если для типа/тега нехватает отведённого места то используется bit-staff (щас уже не модно).

Corba,ldap все банковские сети, pdf и прочие, прочие живут и не жужжат.

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

>поля предваряются тегами в которых содежится инфа о типе,теге и (по необходимости) о длинне.

Пересказал мне мои же слова про псевдо-структуры. ;-) Я не оговаривал точный формат, я говорил про принцип.

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

logIN (*) (18.10.2005 1:48:14):

> Я не оговаривал точный формат, я говорил про принцип.

и я говорил про тот же принцип.

Die-Hard ★★★★★
()
Ответ на: комментарий от MKuznetsov

MKuznetsov (*) (18.10.2005 1:30:53):

> ...не знаю как у них с поддержкой стандартов, но <stdint.h> из С99 должен быть..

BTW,

man gcc:

"... ISO C99. Note that this standard is not yet fully supported; see <http://gcc.gnu.org/gcc-3.1/c99status.html>; for more information."

From http://gcc.gnu.org/gcc-3.1/c99status.html:

... extended integer types in <stdint.h> ... Missing.

:-)

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

>> Я не оговаривал точный формат, я говорил про принцип. >и я говорил про тот же принцип.

тут дело не в принципе - для разбора упомянутых двоичных форматов необходимы упакованные структуры, потому как именно в них передаётся служебная информация (те самые теги,типы,длины..).

Так что никуда от этого не дется, а надо смело использовать uint16_t и иже с ним, и возможно страшась несовместимости с другими компилерами определять выравнивание/упаковку через define.

и кстати вопрос в теме был совершенно конкретный - про то как прочесть из файла заданную структуру, а не про то как эту струкуру лучше сделать.

MKuznetsov ★★★★★
()
Ответ на: комментарий от Die-Hard

DieHard : "... extended integer types in <stdint.h> ... Missing."

- речь идет о int_leastXX_t int_fastXX_t

MKuznetsov ★★★★★
()
Ответ на: комментарий от Die-Hard

> Везде, где можно, следует избегать писать в файлы "голые" структуры. "Rule of thumb". Один из наиболее мешающих жить источников несовместимостей.

вам ехать или как? в теории - кто бы спорил, давайте всё нарежем в XML. в практичке есть формат BMP, он от рождения бинарный причём даже без указания byte order и пр. мелочи жизни и ничего с этим поделать нельзя - он уже есть. что теперь, автору поста застрелиться? дельное предложение, уж куда лучше :-/

__attribute__((packed)) на gcc, #pragma pack() [в ралзичных вариациях в зависимости от версии] на Watcom, очевидно, что-то своё на msvc или icc и так далее. и ничего с этим поделать нельзя бо стандарта на это нет ни в C ни в C++. грустно, но работать тем не менее надо.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от Die-Hard

>Везде, где можно, следует избегать писать в файлы "голые" структуры. "Rule of thumb". Один из наиболее мешающих жить источников несовместимостей.

Зато как быстро их потом mmap поднимает...

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

MKuznetsov(*) (18.10.2005 2:31:05):

> Так что никуда от этого не дется, а надо смело использовать uint16_t и иже с ним, и возможно страшась несовместимости с другими компилерами определять выравнивание/упаковку через define.

Ради Бога! Охота приключений -- ССЗБ. Пионерия на марше...

Вот от таких насторений в последнее время Линух все более несовместим сам с собой. Дошло до того, что бинарники порой приходится затачивать под разные дистрибутивы с одной и той же libc.

Die-Hard ★★★★★
()

Запомни: НИКОГДА НЕЛЬЗЯ ЧИТАТЬ СТРУКТУРЫ ИЗ ФАЙЛОВ. НИКОГДА НЕЛЬЗЯ ПИСАТЬ СТРУКТУРЫ В ФАЙЛЫ. За такое надо бить лопатой по голове!

Во первых, как ты сам заметил, выравнивание. Во вторых - endiannes. В третьих - не гарантированная разрядность стандартных типов данных.

Структуры не для I/O. Структуры - это ВНУТРЕННЕЕ представление.

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

Деточка, ответ "НИКАК" - абсолютно правильный. Потому что с этой дурной прагмой ты пойдёшь в анальный тухес, например, на Sparc-е, на Sun Workshop. Есть архитектуры, где доступ без выравнивания - трап. Не знал, деточка?

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

>Структуры не для I/O. Структуры - это ВНУТРЕННЕЕ представление

Включайте логику, наконец.

>НИКОГДА НЕЛЬЗЯ ЧИТАТЬ СТРУКТУРЫ ИЗ ФАЙЛОВ. НИКОГДА НЕЛЬЗЯ ПИСАТЬ СТРУКТУРЫ В ФАЙЛЫ...

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

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

linux очень сильно завязан на gcc. Простительно, хотя и стоило бы расстрелять засранцев. Прикладному программисту такое не прощают никогда.

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

Не в любом, деточка. Некоторые архитектуры не допускают вообще нарушений выравнивания.

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

Ты зря так уверен. Большинство СУБД пишет структуры поэлементно.

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

>Зачем писать в файлы указатели?!?

Затем, чтобы их оттуда _быстро_ читать. Пример - есть "демон", обслуживающая несколько тысяч устройств. Чтобы делать это быстро, он _должен_ иметь все необходимое в памяти и в правильных(оптимизированых) структурах. Построить эти структуры стоит несколько минут, во время которых устройства не обслуживаются. Клиентам это не нравится.

А так - построил отдельной програмкой, сохранил, в демоне mmap вызвал, за почти 0вое время, и работай себе.

Конечно, можно написать ленивую структуру, с отложеным строительством(хаскель рулит). Но не везде получится. Например YUM-у с его xml-ным repodata это ни разу не светит. И он, бедный, при каждом запуске секунд по 20 вынужден делать одну и ту же бессмысленную работу.

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

Вот именно, что mmap. Сам то понял, что сказал? mmap-ай хоть до посинения, это твой личный, частный своп, который никому больше не дашь.

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

>НИКОГДА НЕЛЬЗЯ ЧИТАТЬ СТРУКТУРЫ ИЗ ФАЙЛОВ. НИКОГДА НЕЛЬЗЯ ПИСАТЬ СТРУКТУРЫ В ФАЙЛЫ.

Вы лиспокодер? Откуда такой идеализм? Загляните на досуге в формат ELF _файлов_ и ужаснитесь. Везде структуры и смещения. Живут же, не помирают? Поэтому не надо говорить чушь.

И напоследок, rule of thumb: "никогда не говори никогда".

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

Лиспнюки идут туда же, куда фанаты XML-я, со своей сериализацией всего подряд в текстовые форматы. ELF - дерьмо. Попробуй со своими уродскими структурами JPEG почитать, посмеёмся.

Кошерный способ описан в интерфейсе java.io.Serializable. В Си такое тоже очень просто делается, как пример - смотреть на PVM.

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

DonkeyHot (18.10.2005 15:57:06):

>Пример - есть "демон", обслуживающая несколько тысяч устройств. Чтобы делать это быстро, он _должен_ иметь все необходимое в памяти и в правильных(оптимизированых) структурах. Построить эти структуры стоит несколько минут, во время которых устройства не обслуживаются. ... А так - построил отдельной програмкой, сохранил, в демоне mmap вызвал, за почти 0вое время, и работай себе.

Тот самый случай, когда хаки с прагмами не годятся.

Ты действительно веришь, что _упакованная_ структура является _оптимизированной_? Весь бенефит от чтения структуры mmap'ом вместо поэлементного чтения (уверяю, бенефит этот составит в лучшем случае проценты) будет съеден первой же операцией доступа к полю невыровненной структуры.

Die-Hard ★★★★★
()
Ответ на: комментарий от JavaHarlal

>ELF - дерьмо.

Все понял.

...Как интересно, человек может сказать о себе практически все, всего двумя словами - "ELF - дерьмо".

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