Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Endian Arithmetic Types

Boost , ,

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Endian Home    Функции преобразования   Арифметические типы   Буферные типы   Выбор подхода

Contents
Introduction
Example
Limitations
Feature set
Enums and typedefs
Class template endian
    Synopsis
    Members
    Stream inserter
    Stream extractor
FAQ
Design
Experience
Motivating use cases
C++11
Compilation
Acknowledgements

Introduction

Headerboost/endian/arithmetic.hppобеспечивает целые двоичные типы с контролем порядка байтов, типа значений, размера и выравнивания. Typedefs предоставляют простые в использовании имена для общих конфигураций.

Эти типы предоставляют портативные держатели байтов для целочисленных данных, независимо от конкретных компьютерных архитектур. Случаи использования почти всегда включают в себя ввод/вывод либо через файлы, либо через сетевые соединения. Хотя переносимость данных является основной мотивацией, эти целочисленные держатели байтов могут также использоваться для уменьшения использования памяти, размера файла или сетевой активности, поскольку они обеспечивают двоичные целочисленные размеры, недоступные в противном случае.

Такие целочисленные байтодержатели традиционно называютэндианамитипами. См.Википедиядля полного изученияэндианности, включая определениябольшого эндианаималенького эндиана.

Эндиевые целые числа Boost обеспечивают тот же полный набор назначений C++, арифметических и реляционных операторов как стандартные интегральные типы C++ со стандартной семантикой.

Унарными арифметическими операторами являются<+>,<->,<~>,<!>, плюс префикс и постфикс<-->и<++>. Бинарные арифметические операторы:<+>,<+=>,<->,< -=>,<*>,<*=>,</>,</=>,<&>,<&=>,<|>,<|=>,<^>,<^=>,<<<>,<<<=>,< >><>>=>. Бинарные реляционные операторы:<==>,<!=>,<<>,<<=>,<>>и<>=>.

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

Example

Программаendian_example.cppпишет двоичный файл, содержащий четырехбайтовые, большие и малые целые числа:

#include <iostream>
#include <cstdio>
#include <boost/endian/arithmetic.hpp>
#include <boost/static_assert.hpp>
using namespace boost::endian;
namespace 
{
  //  This is an extract from a very widely used GIS file format.
  //  Why the designer decided to mix big and little endians in
  //  the same file is not known. But this is a real-world format
  //  and users wishing to write low level code manipulating these
  //  files have to deal with the mixed endianness.
  struct header
  {
    big_int32_t     file_code;
    big_int32_t     file_length;
    little_int32_t  version;
    little_int32_t  shape_type;
  };
  const char* filename = "test.dat";
}
int main(int, char* [])
{
  header h;
  BOOST_STATIC_ASSERT(sizeof(h) == 16U);  // reality check
  
  h.file_code   = 0x01020304;
  h.file_length = sizeof(header);
  h.version     = 1;
  h.shape_type  = 0x01020304;
  //  Low-level I/O such as POSIX read/write or <cstdio>
  //  fread/fwrite is sometimes used for binary file operations
  //  when ultimate efficiency is important. Such I/O is often
  //  performed in some C++ wrapper class, but to drive home the
  //  point that endian integers are often used in fairly
  //  low-level code that does bulk I/O operations, <cstdio>
  //  fopen/fwrite is used for I/O in this example.
  std::FILE* fi = std::fopen(filename, "wb");  // MUST BE BINARY
  
  if (!fi)
  {
    std::cout << "could not open " << filename << '\n';
    return 1;
  }
  if (std::fwrite(&h, sizeof(header), 1, fi)!= 1)
  {
    std::cout << "write failure for " << filename << '\n';
    return 1;
  }
  std::fclose(fi);
  std::cout << "created file " << filename << '\n';
  return 0;
}

После компиляции и выполненияendian_example.cpp, шестнадцатеричный слив<test.dat>показывает:

01020304 00000010 01000000 04030201

Обратите внимание, что первые два 32-разрядных целых числа являются большими эндианами, а вторые два — маленькими эндианами, хотя машина, на которой это было составлено и запущено, была малоэндианной.

Limitations

Для этого необходимо<<climits>><CHAR_BIT == 8>. Если<CHAR_BIT>является неким другим значением, то компиляция приведет к<#error>. Это ограничение существует, потому что при проектировании, внедрении, тестировании и документации учитывались только проблемы, связанные с 8-битными байтами, и не было представлено реальных вариантов использования для других размеров.

В C++03<endian_arithmetic>не соответствует требованиям для типов POD, поскольку имеет конструкторы, частные члены данных и базовый класс. Это означает, что общие случаи использования основаны на неопределенном поведении в том, что C++ Стандарт не гарантирует макет памяти для не-POD типов. Это не было проблемой на практике, так как все известные компиляторы C++ выкладывают память, как если бы< endian>были POD-типом. В C++11 можно указать конструктор по умолчанию как тривиальный, а частные члены данных и базовые классы больше не дисквалифицируют тип от типа POD. Таким образом, в C++11<endian_arithmetic>больше не будет полагаться на неопределенное поведение.

Feature set

  • Большой эндиан | малый эндиан | нативный эндиан байтовый порядок.
  • неподписанный
  • Неприсоединившийся
  • 1-8 байт (необязательный) | 1, 2, 4, 8 байт (выровненный)
  • Выбор типа ценности

Enums and typedefs

Предусмотрены два тематических перечня:

enum class order {big, little, native};
enum class align {no, yes}; 

Предоставляется один шаблон класса:

template <order Order, typename T, std::size_t n_bits,
  align Align = align::no>
class endian_arithmetic;

Типдефы, такие как<big_int32_t>, обеспечивают удобные соглашения об именах для общих случаев использования:

Name Alignment Endianness Sign Sizes in bits (n)
big_intn_t no big signed 8,16,24,32,40,48,56,64
big_uintn_t no big unsigned 8,16,24,32,40,48,56,64
little_intn_t no little signed 8,16,24,32,40,48,56,64
little_uintn_t no little unsigned 8,16,24,32,40,48,56,64
native_intn_t no native signed 8,16,24,32,40,48,56,64
native_uintn_t no native unsigned 8,16,24,32,40,48,56,64
big_intn_at yes big signed 8,16,32,64
big_uintn_at yes big unsigned 8,16,32,64
little_intn_at yes little signed 8,16,32,64
little_uintn_at yes little unsigned 8,16,32,64

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

Предупреждение:Код, который используетзажигаемые типы, возможно, непортативный, потому что требования выравнивания различаются между аппаратными архитектурами и потому, что выравнивание может быть затронуто коммутаторами компилятора или прагмами. Например, выравнивание 64-битного целого числа может быть на 32-битной границе на 32-битной машине. Кроме того, выровненные типы доступны только в архитектурах с 8, 16, 32 и 64-разрядными целыми типами.

Рекомендация:Предпочитают невыровненные арифметические типы.

Рекомендация:Защитите себя от болезней выравнивания. Например:

static_assert(sizeof(containing_struct) == 12, "sizeof(containing_struct) is wrong"); 

Примечание:Примечание:Однобайтовые арифметические типы имеют одинаковую компоновку на всех платформах, поэтому они никогда не обращают вспять эндианность. Они предоставляются для обеспечения универсального кода, а также для улучшения читаемости и поиска кода.

Class template endian_arithmetic

<endian_integer>представляет собой целочисленный байтодержатель с эндианностьюпользователя, типом значения, размером ивыравниванием. Поставляются обычные операции по арифметическим типам.

Synopsis

#include <boost/endian/conversion.hpp>
#include <boost/endian/buffers.hpp>
namespace boost
{
  namespace endian
  {
    //  C++11 features emulated if not available
   
    enum class align {no, yes};            
    template <order Order, class T, std::size_t n_bits,
      align Align = align::no>
    class endian_arithmetic
      : public endian_buffer<Order, T, n_bits, Align>
    {
    public:
      typedef T value_type;
      // if BOOST_ENDIAN_FORCE_PODNESS is defined && C++11 PODs are not
      // available then these two constructors will not be present
      endian_arithmetic() noexcept = default;
      endian_arithmetic(T v) noexcept;
      endian_arithmetic& operator=(T v) noexcept;
      operator value_type() const noexcept;
      value_type value() const noexcept; // for exposition; see endian_buffer
      const char* data() const noexcept; // for exposition; see endian_buffer
      // arithmetic operations
      //   note that additional operations are provided by the value_type 
      value_type operator+(const endian& x) noexcept;
      endian& operator+=(endian& x, value_type y) noexcept;
      endian& operator-=(endian& x, value_type y) noexcept;
      endian& operator*=(endian& x, value_type y) noexcept;
      endian& operator/=(endian& x, value_type y) noexcept;
      endian& operator%=(endian& x, value_type y) noexcept;
      endian& operator&=(endian& x, value_type y) noexcept;
      endian& operator|=(endian& x, value_type y) noexcept;
      endian& operator^=(endian& x, value_type y) noexcept;
      endian& operator<<=(endian& x, value_type y) noexcept;
      endian& operator>>=(endian& x, value_type y noexcept;
      value_type operator<<(const endian& x, value_type y) noexcept;
      value_type operator>>(const endian& x, value_type y) noexcept;
      endian& operator++(endian& x) noexcept;
      endian& operator--(endian& x) noexcept;
      endian operator++(endian& x, int) noexcept;
      endian operator--(endian& x, int) noexcept;
      // Stream inserter
      template <class charT, class traits>
      friend std::basic_ostream<charT, traits>&
        operator<<(std::basic_ostream<charT, traits>& os, const T& x);
      // Stream extractor 
      template <class charT, class traits>
      friend std::basic_istream<charT, traits>&
        operator>>(std::basic_istream<charT, traits>& is, T& x);
    };
    // typedefs  
    // unaligned big endian signed integer types
    typedef endian<order::big, int_least8_t, 8>        big_int8_t;
    typedef endian<order::big, int_least16_t, 16>      big_int16_t;
    typedef endian<order::big, int_least32_t, 24>      big_int24_t;
    typedef endian<order::big, int_least32_t, 32>      big_int32_t;
    typedef endian<order::big, int_least64_t, 40>      big_int40_t;
    typedef endian<order::big, int_least64_t, 48>      big_int48_t;
    typedef endian<order::big, int_least64_t, 56>      big_int56_t;
    typedef endian<order::big, int_least64_t, 64>      big_int64_t;
  
    // unaligned big endian unsigned integer types
    typedef endian<order::big, uint_least8_t, 8>       big_uint8_t;
    typedef endian<order::big, uint_least16_t, 16>     big_uint16_t;
    typedef endian<order::big, uint_least32_t, 24>     big_uint24_t;
    typedef endian<order::big, uint_least32_t, 32>     big_uint32_t;
    typedef endian<order::big, uint_least64_t, 40>     big_uint40_t;
    typedef endian<order::big, uint_least64_t, 48>     big_uint48_t;
    typedef endian<order::big, uint_least64_t, 56>     big_uint56_t;
    typedef endian<order::big, uint_least64_t, 64>     big_uint64_t;
    // unaligned little endian signed integer types
    typedef endian<order::little, int_least8_t, 8>     little_int8_t;
    typedef endian<order::little, int_least16_t, 16>   little_int16_t;
    typedef endian<order::little, int_least32_t, 24>   little_int24_t;
    typedef endian<order::little, int_least32_t, 32>   little_int32_t;
    typedef endian<order::little, int_least64_t, 40>   little_int40_t;
    typedef endian<order::little, int_least64_t, 48>   little_int48_t;
    typedef endian<order::little, int_least64_t, 56>   little_int56_t;
    typedef endian<order::little, int_least64_t, 64>   little_int64_t;
  
    // unaligned little endian unsigned integer types
    typedef endian<order::little, uint_least8_t, 8>    little_uint8_t;
    typedef endian<order::little, uint_least16_t, 16>  little_uint16_t;
    typedef endian<order::little, uint_least32_t, 24>  little_uint24_t;
    typedef endian<order::little, uint_least32_t, 32>  little_uint32_t;
    typedef endian<order::little, uint_least64_t, 40>  little_uint40_t;
    typedef endian<order::little, uint_least64_t, 48>  little_uint48_t;
    typedef endian<order::little, uint_least64_t, 56>  little_uint56_t;
    typedef endian<order::little, uint_least64_t, 64>  little_uint64_t;
    // unaligned native endian signed integer types
    typedef implementation-defined_int8_t   native_int8_t;
    typedef implementation-defined_int16_t  native_int16_t;
    typedef implementation-defined_int24_t  native_int24_t;
    typedef implementation-defined_int32_t  native_int32_t;
    typedef implementation-defined_int40_t  native_int40_t;
    typedef implementation-defined_int48_t  native_int48_t;
    typedef implementation-defined_int56_t  native_int56_t;
    typedef implementation-defined_int64_t  native_int64_t;
    // unaligned native endian unsigned integer types
    typedef implementation-defined_uint8_t   native_uint8_t;
    typedef implementation-defined_uint16_t  native_uint16_t;
    typedef implementation-defined_uint24_t  native_uint24_t;
    typedef implementation-defined_uint32_t  native_uint32_t;
    typedef implementation-defined_uint40_t  native_uint40_t;
    typedef implementation-defined_uint48_t  native_uint48_t;
    typedef implementation-defined_uint56_t  native_uint56_t;
    typedef implementation-defined_uint64_t  native_uint64_t;
    
    // aligned big endian signed integer types
    typedef endian<order::big, int8_t, 8, align::yes>       big_int8_at;
    typedef endian<order::big, int16_t, 16, align::yes>     big_int16_at;
    typedef endian<order::big, int32_t, 32, align::yes>     big_int32_at;
    typedef endian<order::big, int64_t, 64, align::yes>     big_int64_at;
    // aligned big endian unsigned integer types
    typedef endian<order::big, uint8_t, 8, align::yes>      big_uint8_at;
    typedef endian<order::big, uint16_t, 16, align::yes>    big_uint16_at;
    typedef endian<order::big, uint32_t, 32, align::yes>    big_uint32_at;
    typedef endian<order::big, uint64_t, 64, align::yes>    big_uint64_at;
    // aligned little endian signed integer types
    typedef endian<order::little, int8_t, 8, align::yes>    little_int8_at;
    typedef endian<order::little, int16_t, 16, align::yes>  little_int16_at;
    typedef endian<order::little, int32_t, 32, align::yes>  little_int32_at;
    typedef endian<order::little, int64_t, 64, align::yes>  little_int64_at;
    // aligned little endian unsigned integer types
    typedef endian<order::little, uint8_t, 8, align::yes>   little_uint8_at;
    typedef endian<order::little, uint16_t, 16, align::yes> little_uint16_at;
    typedef endian<order::little, uint32_t, 32, align::yes> little_uint32_at;
    typedef endian<order::little, uint64_t, 64, align::yes> little_uint64_at;
    // aligned native endian typedefs are not provided because
    // <cstdint> types are superior for that use case
  
  } // namespace endian
} // namespace boost

Текст<implementation-defined>выше либо<big>, либо<little>в соответствии с эндианностью платформы.

Members

endian() = default;  // C++03: endian(){}

Эффекты:Конструирует неинициализированный объект типа<endian_arithmetic<E, T, n_bits, A>>.

endian(T v);

Эффекты:Конструирует объект типа<endian_arithmetic<E, T, n_bits, A>>.

Постсостояние:<x == v,>, где<x>является сконструированным объектом.

endian& operator=(T v);

Постсостояние:<x == v,>, где<x>является сконструированным объектом.

Возвращение:<*this>.

operator T() const;

Возвращение:Текущее значение, сохраненное в<*this>, преобразовано в<value_type>.

const char* data() const;

Возврат:Указатель на первый байт эндианового двоичного значения, хранящегося в<*this>.

Other operators

Другие операторы на эндианных объектах направляются эквивалентному оператору на<value_type>.

Stream inserter

template <class charT, class traits>
friend std::basic_ostream<charT, traits>&
  operator<<(std::basic_ostream<charT, traits>& os, const T& x);

Возвращение:<os << +x>.

Stream extractor

template <class charT, class traits>
friend std::basic_istream<charT, traits>&
  operator>>(std::basic_istream<charT, traits>& is, T& x);

Эффекты:Как будто:

T i;
if (is >> i)
  x = i;

Возвращение:<is>

FAQ

См. домашнюю страницуEndianFAQ для FAQ в библиотеке.

Почему бы просто не использовать Boost.Serialization?Сериализация включает в себя преобразование для каждого объекта, участвующего в I/O. Эндиевые целые числа не требуют преобразования или копирования. Они уже в нужном формате для двоичного ввода/вывода. Таким образом, их можно читать или писать навалом.

Являются ли эндианные типы POD?Да, для C++11. Нет для C++03, хотя несколькомакросовдоступны для форсирования PODness во всех случаях.

Каковы последствия того, что целые типы эндиев не являются POD с компиляторами C++03?Они не могут быть использованы в профсоюзах. Кроме того, компиляторы не обязаны выравнивать или размещать хранилище портативными способами, хотя эта потенциальная проблема не помешала использованию Boost. Эндиан с реальными компиляторами.

Что хорошего вродномэндианстве?Он обеспечивает выравнивание и гарантии размера, недоступные для встроенных типов. Упрощает общее программирование.

Зачем беспокоиться о выровненных типах эндиев?Выровненные операции с целым числом могут быть быстрее (в 10-20 раз быстрее), если эндианность и выравнивание типа соответствуют требованиям эндианности и выравнивания машины. Код, однако, будет несколько менее портативным, чем с неприсоединившимися типами.

Зачем проводить арифметические операции?Предоставление полного набора операций уменьшает загромождение программ и облегчает запись и чтение кода. Рассмотрите возможность увеличения переменной в записи. Очень удобно писать:

    ++record.foo;

Rather than:

    int temp(record.foo);
    ++temp;
    record.foo = temp;

Design considerations for Boost.Endian types

  • Должна быть пригодна для ввода/вывода - другими словами, должна быть мемкопируемой.
  • Необходимо точно указать размер и внутренний байт заказа.
  • Должен работать правильно, когда внутреннее целое представление имеет больше битов, чем сумма битов во внешнем представлении байта. Расширение знака должно работать правильно, когда тип представления внутреннего целого числа имеет больше битов, чем сумма битов во внешних байтах. Например, использование 64-битного целого числа внутри для представления 40-битных (5 байт) чисел должно работать как для положительных, так и для отрицательных значений.
  • Должен работать правильно (включая использование одного и того же определенного внешнего представления) независимо от того, относится ли компилятор к char как к подписанному или неподписанному.
  • Несогласованные типы не должны заставлять компиляторы вставлять байты прокладки.
  • Реализация должна обеспечить оптимизацию с большой осторожностью. Опыт показал, что оптимизация целых чисел часто становится пессимизацией при смене машин или компиляторов. Пессимизации также могут происходить при изменении коммутаторов компилятора, версий компилятора или моделей процессоров той же архитектуры.

Experience

Классы с аналогичной функциональностью были независимо разработаны несколькими программистами Boost и в течение многих лет успешно использовались в высококачественных приложениях. Эти независимо разработанные эндианные библиотеки часто развивались из библиотек C, которые также широко использовались. Типы Endian оказались широко полезными в широком спектре компьютерных архитектур и приложений.

Motivating use cases

Нил Мэйхью пишет: "Я также могу предоставить значимый вариант использования для этой библиотеки: чтение Правды Введите файлы шрифтов с диска и обработайте содержимое. Формат данных имеет фиксированную эндианность (большую) и имеет несогласованные значения в различных местах. Используя Boost. Эндиан прекрасно упрощает и очищает код. ";

C++11

Доступность функции C++11Defaulted Functionsобнаруживается автоматически и будет использоваться, если присутствует, для обеспечения того, чтобы объекты<class endian_arithmetic>были тривиальными, и, следовательно, POD.

Compilation

Повышаю. Endian полностью реализован в заголовках, без необходимости ссылаться на какие-либо библиотеки объектов Boost.

Несколько макросов позволяют пользователю контролировать функции:

  • BOOST_ENDIAN_NO_CTORS (0) не имеет строителей. Предполагаемое использование предназначено для компиляции пользовательского кода, который должен быть портативным между компиляторами независимо от поддержки C++11Defaulted Functions. Использование конструкторов всегда будет неудачным
    .
  • BOOST_ENDIAN_FORCE_PODNESS BOOST_ENDIAN_NO_CTORS определяется, если компилятор не поддерживает C++11. Это гарантирует, что объектыclass endian_arithmeticявляются POD, и поэтому могут использоваться в союзах C++03. В C++11class endian_arithmeticобъекты являются POD, хотя у них есть конструкторы, поэтому их всегда можно использовать в союзах.

Acknowledgements

Оригинальный дизайн разработан Дарином Адлером на основе классов, разработанных Марком Боргердингом. Четыре оригинальных шаблона классов, объединенных в один<endian_arithmetic>шаблон класса Беманом Доусом, который собрал библиотеку вместе, предоставил документацию, добавил типдефы, а также добавил<unrolled_byte_loops>знак частичной специализации, чтобы правильно расширить знак, когда размер покрытия целым числом отличается от размера эндианного представления.


Последнее изменение:14 октября 201514 October, 2015[ORIG_END] -->

© Copyright Beman Dawes, 2006-2009, 2013

Распространяется в соответствии с Лицензией на программное обеспечение Boost, версия 1.0. См.www.boost.org/ LICENSE_1_0.txt

Статья Endian Arithmetic Types раздела может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 16:08:42/0.0076620578765869/0