LINUX.ORG.RU

Внутреннее представление объекта зависит от реализации ???

 ,


0

1

Добрый день.
Возможно вопрос соответствует не очень высокому уровню, прошу прощения, если что.
Вот есть такой код в книге «Язык программирования C++ С. Прата»:

const int LIM = 20;
struct planet {
    char name[LIM];
    double population;
    double g;
};
planet pi;

// Сохранение объекта pi в файл:
fout("planets.dat",ios_base::out | ios_base::app | ios_base::binary);
fout.write((char*) &pl, sizeof pi);
Правильно ли я понимаю, что внутреннее представление объекта pi принадлежащего структуре/классу planet определяется реализацией компилятора и не оговорено стандартом? И тот же вопрос для случая, когда среди членов класса будут объекты других классов, контейнеры, умные указатели и прочее. Немного уточню вопрос: массив char получающийся в итоге и сохраненный в файле будет одинаковый на разных платформах и компиляторах и оговорено ли в стандарте то какой будет этот масссив (т.е. оговорено ли, какое будет побайтовое представление объекта в памяти)?

UPD0 Помечу, что для единообразного преобразования числа в массив байт, и последующего единообразного обратного преобразования (даже при том, что эти преобразования могут быть выполнены на разных пк (например при передаче по сети) в программах, которые были скомпилированы разными компиляторами) можно использовать:
Boost.Lexical_Cast
std::stringstream (указано в документации к Boost.Lexical_Cast)
Qt QDataStream

★★★★★

Только очередность в std::is_standard_layout гарантировано будет сохраняться. Выравнивание нет. Представление каждого поля, в общем случае тоже нет (зависит от типа).

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

Очерёдность гарантирована в пределах одной области доступа (private, public, protected), не только для standard_layout.
По теме, да, внутреннее представление не стандартизовано. Ни его размер, ни битики, из которых обьект должен состоять. Там есть некоторые ограничения, но это детали. Не надо на него закладываться, плохо кончается.

Gvidon ★★★★ ()

не только выравнивание. в некоторых реализациях ещё и мусор может остаться в незаполненных байтах, если специально не чистить память. часто на это наступают программисты, которые не учитывают реализации на разных платформах.

з.ы. предлагаю 27 августа объявить днём выравнивания данных на ЛОРе. за последние два дня уже три треда на эту тему в девелопменте. все озаботились упаковкой данных :)

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

з.ы. предлагаю 27 августа объявить днём выравнивания данных на ЛОРе. за последние два дня уже три треда на эту тему в девелопменте. все озаботились упаковкой данных :)

Улыбнуло. И да, согласен.

rumgot ★★★★★ ()

Внутреннее представление объекта зависит от реализации ???

Да. Зависит от компилятора, архитектуры, ОС, версий всего этого.

Стандарт лишь гарантирует порядок следования полей в структуре/классе, если оно POD, но выравнивание и внутреннее предоставление каждого базового типа (например, LE/BE) полностью платфрмо-специфично.

Если собираешься сохранять структуру на диск, то необходимый минимум:

1) Структура должна быть POD

2) Структура должна быть упакована (packed)

3) Числовые поля необходимо привести к гарантированному порядку байт (endianess.h в помощь)

4) Использовать числовые типы с гарантированным размером (stdint.h в помощь - int8_t, uint32_t и т. д.)

5) Разумеется, никаких указателей в структуре (они имеют смысл только в конкретный запуск приложения и даже в конкретный момент его работы)

Если нарушить хоть один пункт, то это гарантированный выстрел в ногу.

KivApple ★★★★★ ()

Вот есть такой код в книге «Язык программирования C++ С. Прата».

Спасибо. Добавил в список книг, которые не буду рекомендовать.

anonymous ()

Подведем итог. Если у нас имеется тривиально копируемый тип. То переменная такого типа может быть побайтно скопирована в виде массива char и затем однозначно восстановлена из этого байтового массива (например с использованием memcpy). Но это справедливо только в рамках одного работающего процесса. Т.к. это внутреннее байтовое представление объекта зависит от реализации компилятора/платформы и не оговорено стандартом. Т.е. использовать данный прием для сохранения оъекта на диске или отправки его по сети нельзя. Все ли правильно?

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

Прата на самом деле особый случай, я в шоке от того как за него шиллят на форумах.

Отличный учебник по основам C++. Также дается некоторая информация о C++11. Чем он вам не угодил?

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

Можно, только нужно использовать точные типы никаких long, структура должна быть целостной без дыр и пустых хвостов, а также записывать и читать структуру нужно побайтово дабы порядок байт в системе значения не имел. Ну… если у тебя есть Сетунь-70 в поддержке то наверное уже нельзя =)

(Поправьте меня если что)

LINUX-ORG-RU ★★ ()
Ответ на: комментарий от anonymous

Определение посмотри в вики:

Объект в программировании — некоторая сущность в цифровом пространстве, обладающая определённым состоянием и поведением, имеющая определенные свойства (атрибуты) и операции над ними (методы)

У объекта должны быть методы. У обычных переменных и структур никаких методов нет.

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

А почему там? Почему не в стандарте плюсов?

А почему именно в стандарт плюсов, а не в вики?

Стандарт так не считает.

Если имеется ввиду то, что под объектом имеется ввиду в стандарте - да, это тогда все объекты.

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

Если писать новый код, то уже сериализовать каким-то фреймворком. Иначе - гарантированный выстрел в ногу.

Хуже если есть легаси говно и изменение формата данных влечет за собой перестройки и батхарт старперов.

invy ★★★★★ ()
Последнее исправление: invy (всего исправлений: 1)