c ++ нормализует размеры данных в разных системах - PullRequest
2 голосов
/ 28 декабря 2010

У меня есть структура с тремя переменными: два беззнаковых целых и беззнаковый символ.Насколько я понимаю, символ C ++ всегда равен 1 байту независимо от того, в какой операционной системе он работает.То же самое нельзя сказать о других типах данных.Я ищу способ нормализовать POD так, чтобы при сохранении в двоичном файле полученный файл был доступен для чтения в любой операционной системе, для которой скомпилирован код.

Я изменил свою структуру, чтобы использовать 1-байтовое выравнивание, добавив #pragma следующим образом:

#pragma pack(push, 1) 
struct test
{
   int a;
}
#pragma pack(pop)

, но это не обязательно означает, что int a это ровно 4 байта накаждый ос, я не думаю?Есть ли способ гарантировать, что файл, сохраненный из моего кода, всегда будет читабельным?

Ответы [ 4 ]

3 голосов
/ 28 декабря 2010

Вы можете найти целочисленные типы фиксированной ширины (например, std::int32_t и std::uint16_t) в <cstdint>. Ваша реализация Стандартной библиотеки C ++ может не включать <cstdint> (это не является частью текущего стандарта C ++; это часть C ++ 0x), в этом случае Boost имеет реализацию , которая должна работать на большинстве платформ.

Обратите внимание, что вам все равно придется подумать о порядке байтов и выравнивании, между прочим. Если ваш код должен работать на платформах с разными числовыми представлениями (например, одно дополнение и два дополнения), вам необходимо учитывать это тоже.

0 голосов
/ 29 декабря 2010

Правильный способ сделать это - сериализовать данные в стандартном формате.Есть много стандартов для этого.Для простоты CSV равен единице (переменные, разделенные запятыми).Если вы хотите более эффективный стандарт, попробуйте XDR, или, который часто используется в телекоммуникационной отрасли, ASN.1.

0 голосов
/ 28 декабря 2010

Невозможно просто так написать двоичную структуру и сделать ее доступной для чтения любой системой.Хотя вы можете использовать некоторую библиотеку, которая определяет типы, такие как int32, это не решит вашу проблему.

Различные процессоры используют разные порядки байтов и могут требовать различного выравнивания.Кроме того, заполнение зависит от реализации.К счастью, все текущие процессоры, о которых я знаю, используют двойное дополнение для целочисленного представления, а не однозначное или знаковое, поэтому целые числа, по крайней мере, имеют одинаковое двоичное представление (по порядку байтов по модулю).

Нет #pragma может быть действительно переносимым решением, так как они по определению определены реализацией, и вы не можете быть уверены, что разные компиляторы будут обращаться с ними одинаково.Еще несколько спецификаторов работают над следующим стандартом C ++, но в течение некоторого времени они не будут такими уж общими.

Что вам нужно будет сделать, это указать struct с помощьючто-то вроде int32, а затем разбить его на поток байтов и снова собрать на другом конце.Посмотрите "сериализация".

0 голосов
/ 28 декабря 2010

Если вас интересуют 32-битные Windows, 64-битные Windows, Linux (x86 и AMD64) и Mac (x86, AMD64, PPC), то это проще. Int всегда будет 32-битным во всех этих системах. Если вы можете позволить сбросить PPC, он также будет всегда в порядке байтов. Если вам нужна поддержка систем с прямым порядком байтов, я рекомендую хранить данные в сетевом порядке байтов, используя ntohl / htonl.

...