4 <meta http-equiv=
"Content-Language" content=
"en-us">
5 <meta name=
"GENERATOR" content=
"Microsoft FrontPage 5.0">
6 <meta name=
"ProgId" content=
"FrontPage.Editor.Document">
7 <meta http-equiv=
"Content-Type" content=
"text/html; charset=windows-1252">
8 <title>Boost Endian Integers
</title>
9 <link rel=
"stylesheet" type=
"text/css" href=
"../../../doc/html/minimal.css">
15 <table border=
"0" cellpadding=
"5" cellspacing=
"0" style=
"border-collapse: collapse" bordercolor=
"#111111">
18 <a href=
"../../../index.html">
19 <img src=
"../../../boost.png" alt=
"boost.png (6897 bytes)" align=
"middle" width=
"277" height=
"86" border=
"0"></a></td>
20 <td width=
"337" align=
"middle">
21 <font size=
"7">Endian Integers
</font>
26 <table border=
"0" cellpadding=
"5" cellspacing=
"0" style=
"border-collapse: collapse" bordercolor=
"#111111" bgcolor=
"#D7EEFF" width=
"100%">
28 <td><a href=
"../../../index.htm">Boost Home
</a> Tutorial
</td>
32 <table border=
"1" cellpadding=
"5" cellspacing=
"0" style=
"border-collapse: collapse" bordercolor=
"#111111" align=
"right">
34 <td width=
"100%" bgcolor=
"#D7EEFF" align=
"center">
35 <i><b>Contents
</b></i></td>
38 <td width=
"100%" bgcolor=
"#E8F5FF">
39 <a href=
"#Introduction">Introduction
</a><br>
40 <a href=
"#Hello-endian-world">Hello endian world
</a><br>
41 <a href=
"#Limitations">Limitations
</a><br>
42 <a href=
"#Feature-set">Feature set
</a><br>
43 <a href=
"#Types">Typedefs
</a><br>
44 <a href=
"#Comment-on-naming">Comment on naming
</a><br>
45 <a href=
"#Class_template_endian">Class template
<code>endian
</code></a><br>
47 <a href=
"#Synopsis">Synopsis
</a><br>
48 <a href=
"#Members">Members
</a><br>
49 <a href=
"#FAQ">FAQ
</a><br>
50 <a href=
"#Binary-I-O-cautions">Binary I/O warnings and cautions
</a><br>
51 <a href=
"#Example">Example
</a><br>
52 <a href=
"#Design">Design
</a><br>
53 <a href=
"#Experience">Experience
</a><br>
54 <a href=
"#C++0x">C++
0x
</a><br>
55 <a href=
"#Compilation">Compilation
</a><br>
56 <a href=
"#Acknowledgements">Acknowledgements
</a>
60 <td width=
"100%" bgcolor=
"#D7EEFF" align=
"center">
61 <b><i>Headers
</i></b></td>
64 <td width=
"100%" bgcolor=
"#E8F5FF">
65 <a href=
"../../../boost/integer/endian.hpp"><boost/integer/endian.hpp
></a><br>
66 <a href=
"../../../boost/integer/endian_binary_stream.hpp"><boost/integer/endian_binary_stream.hpp
></a><br>
67 <a href=
"../../../boost/binary_stream.hpp"><boost/binary_stream.hpp
></a></td>
70 <h2><a name=
"Introduction">Introduction
</a></h2>
72 <a href=
"../../../boost/integer/endian.hpp"><boost/integer/endian.hpp
></a> provides
73 integer-like byte-holder binary types with explicit control over
74 byte order, value type, size, and alignment. Typedefs provide easy-to-use names
75 for common configurations.
</p>
76 <p>These types provide portable byte-holders for integer data, independent of
77 particular computer architectures. Use cases almost always involve I/O, either via files or
78 network connections. Although data portability is the primary motivation, these
79 integer byte-holders may
80 also be used to reduce memory use, file size, or network activity since they
81 provide binary integer sizes not otherwise available.
</p>
82 <p>Such integer byte-holder types are traditionally called
<b><i>
83 endian
</i></b> types. See the
<a href=
"http://en.wikipedia.org/wiki/Endian">Wikipedia
</a> for
85 exploration of
<b><i>endianness
</i></b>, including definitions of
<i><b>big
86 endian
</b></i> and
<i><b>little endian
</b></i>.
</p>
87 <p>Boost endian integers provide the same full set of C++ assignment,
88 arithmetic, and relational operators
as C++ standard integral types, with
89 the standard semantics.
</p>
90 <p>Unary arithmetic operators are
<code>+
</code>,
<code>-
</code>,
<code>~
</code>,
91 <code>!
</code>, prefix and postfix
<code>--
</code> and
<code>++
</code>. Binary
92 arithmetic operators are
<code>+
</code>,
<code>+=
</code>,
<code>-
</code>,
<code>
93 -=
</code>,
<code>*
</code>,
<code>*=
</code>,
<code>/
</code>,
<code>/=
</code>,
94 <code>%/ %=
</code>,
<code>&</code>,
<code>&=
</code>,
<code>|
</code>,
<code>|=
</code>,
95 <code>^
</code>,
<code>^=
</code>,
<code><<</code>,
<code><<=
</code>,
<code>>></code>,
96 <code>>>=
</code>. Binary relational operators are
<code>==
</code>,
<code>!=
</code>,
97 <code><</code>,
<code><=
</code>,
<code>></code>,
<code>>=
</code>.
</p>
98 <p>Automatic conversion is provided to the underlying integer value type.
</p>
99 <p>Header
<a href=
"../../../boost/integer/endian_binary_stream.hpp"><boost/integer/endian_binary_stream.hpp
></a>
100 provides operators
<= and
<code>=
></code> for unformatted binary (as opposed to
101 formatted character) stream insertion and extraction of endian types.
</p>
102 <p>Header
<a href=
"../../../boost/binary_stream.hpp"><boost/binary_stream.hpp
></a>
103 provides operators
<= and
<code>=
></code> for unformatted binary (as opposed to
104 formatted character) stream insertion and extraction of built-in and std::string
106 <h2><a name=
"Hello-endian-world">Hello endian world
</a></h2>
108 <pre>#include
<boost/integer/endian.hpp
>
109 #include
<boost/integer/endian_binary_stream.hpp
>
110 #include
<boost/binary_stream.hpp
>
111 #include
<iostream
>
113 using namespace boost;
114 using namespace boost::integer;
118 int_least32_t v =
0x31323334L; // = ASCII { '
1', '
2', '
3', '
4' }
119 // value chosen to work on text stream
123 std::cout
<< "Hello, endian world!\n\n
";
125 std::cout
<< v
<< ' '
<< b
<< ' '
<< l
<< '\n';
126 std::cout
<= v
<= ' '
<= b
<= ' '
<= l
<= '\n';
129 <p>On a little-endian CPU, this program outputs:
</p>
131 <pre>Hello, endian world!
133 825373492 825373492 825373492
136 <h2><a name=
"Limitations">Limitations
</a></h2>
137 <p>Requires
<code><climits
></code> <code>CHAR_BIT ==
8</code>. If
<code>CHAR_BIT
</code>
138 is some other value, compilation will result in an
<code>#error
</code>. This
139 restriction is in place because the design, implementation, testing, and
140 documentation has only considered issues related to
8-bit bytes, and there have
141 been no real-world use cases presented for other sizes.
</p>
142 <p>In C++
03,
<code>endian
</code> does not meet the requirements for POD types
143 because it has constructors, private data members, and a base class. This means
144 that common use cases are relying on unspecified behavior in that the C++
145 Standard does not guarantee memory layout for non-POD types. This has not been a
146 problem in practice since all known C++ compilers do layout memory as if
<code>
147 endian
</code> were a POD type. In C++
0x, it will be possible to specify the
148 default constructor as trivial, and private data members and base classes will
149 no longer disqualify a type from being a POD. Thus under C++
0x,
<code>endian
</code>
150 will no longer be relying on unspecified behavior.
</p>
151 <h2><a name=
"Feature-set">Feature set
</a></h2>
153 <li>Big endian| little endian | native endian byte ordering.
</li>
154 <li>Signed | unsigned
</li>
155 <li>Unaligned | aligned
</li>
156 <li>1-
8 byte (unaligned) |
2,
4,
8 byte (aligned)
</li>
157 <li>Choice of integer value type
</li>
159 <h2><a name=
"Types">Typedefs
</a></h2>
160 <p>One class template is provided:
</p>
162 <pre>template
<<a href=
"#endianness">endianness
</a>::enum_t E, typename T, std::size_t n_bytes,
163 <a href=
"#alignment">alignment
</a>::enum_t A = alignment::unaligned
>
167 <p>Sixty typedefs, such as
<code>big32_t
</code>, provide convenient naming
168 conventions for common use cases:
</p>
170 <table border=
"1" cellpadding=
"5" cellspacing=
"0" style=
"border-collapse: collapse" bordercolor=
"#111111" width=
"49%">
172 <td width=
"18%" align=
"center"><b><i>Name
</i></b></td>
173 <td width=
"10%" align=
"center"><b><i>Endianness
</i></b></td>
174 <td width=
"10%" align=
"center"><b><i>Sign
</i></b></td>
175 <td width=
"15%" align=
"center"><b><i>Sizes in bits (n)
</i></b></td>
176 <td width=
"49%" align=
"center"><b><i>Alignment
</i></b></td>
179 <td width=
"18%"><code>big
</code><b><i>n
</i></b><code>_t
</code></td>
180 <td width=
"10%"><code>big
</code></td>
181 <td width=
"10%">signed
</td>
182 <td width=
"15%">8,
16,
24,
32,
40,
48,
56,
64</td>
183 <td width=
"49%"><code>unaligned
</code></td>
186 <td width=
"18%"><code>ubig
</code><i><b>n
</b></i><code>_t
</code></td>
187 <td width=
"10%"><code>big
</code></td>
188 <td width=
"10%">unsigned
</td>
189 <td width=
"15%">8,
16,
24,
32,
40,
48,
56,
64</td>
190 <td width=
"49%"><code>unaligned
</code></td>
193 <td width=
"18%"><code>little
</code><i><b>n
</b></i><code>_t
</code></td>
194 <td width=
"10%"><code>little
</code></td>
195 <td width=
"10%">signed
</td>
196 <td width=
"15%">8,
16,
24,
32,
40,
48,
56,
64</td>
197 <td width=
"49%"><code>unaligned
</code></td>
200 <td width=
"18%"><code>ulittle
</code><i><b>n
</b></i><code>_t
</code></td>
201 <td width=
"10%"><code>little
</code></td>
202 <td width=
"10%">unsigned
</td>
203 <td width=
"15%">8,
16,
24,
32,
40,
48,
56,
64</td>
204 <td width=
"49%"><code>unaligned
</code></td>
207 <td width=
"18%"><code>native
</code><i><b>n
</b></i><code>_t
</code></td>
208 <td width=
"10%"><code>native
</code></td>
209 <td width=
"10%">signed
</td>
210 <td width=
"15%">8,
16,
24,
32,
40,
48,
56,
64</td>
211 <td width=
"49%"><code>unaligned
</code></td>
214 <td width=
"18%"><code>unative
</code><i><b>n
</b></i><code>_t
</code></td>
215 <td width=
"10%"><code>native
</code></td>
216 <td width=
"10%">unsigned
</td>
217 <td width=
"15%">8,
16,
24,
32,
40,
48,
56,
64</td>
218 <td width=
"49%"><code>unaligned
</code></td>
221 <td width=
"18%"><code>aligned_big
</code><i><b>n
</b></i><code>_t
</code></td>
222 <td width=
"10%"><code>big
</code></td>
223 <td width=
"10%">signed
</td>
224 <td width=
"15%">16,
32,
64</td>
225 <td width=
"49%"><code>aligned
</code></td>
228 <td width=
"18%"><code>aligned_ubig
</code><i><b>n
</b></i><code>_t
</code></td>
229 <td width=
"10%"><code>big
</code></td>
230 <td width=
"10%">unsigned
</td>
231 <td width=
"15%">16,
32,
64</td>
232 <td width=
"49%"><code>aligned
</code></td>
235 <td width=
"18%"><code>aligned_little
</code><i><b>n
</b></i><code>_t
</code></td>
236 <td width=
"10%"><code>little
</code></td>
237 <td width=
"10%">signed
</td>
238 <td width=
"15%">16,
32,
64</td>
239 <td width=
"49%"><code>aligned
</code></td>
242 <td width=
"18%"><code>aligned_ulittle
</code><i><b>n
</b></i><code>_t
</code></td>
243 <td width=
"10%"><code>little
</code></td>
244 <td width=
"10%">unsigned
</td>
245 <td width=
"15%">16,
32,
64</td>
246 <td width=
"49%"><code>aligned
</code></td>
250 <p>The unaligned types do not cause compilers to insert padding bytes in classes
251 and structs. This is an important characteristic that can be exploited to minimize wasted space in
252 memory, files, and network transmissions.
</p>
253 <p><font color=
"#FF0000"><b><i><span style=
"background-color: #FFFFFF">Warning:
</span></i></b></font><span style=
"background-color: #FFFFFF">
254 Code that uses a
</span>ligned types is inherently non-portable because alignment
255 requirements vary between hardware architectures and because alignment may be
256 affected by compiler switches or pragmas. Furthermore, aligned types
257 are only available on architectures with
16,
32, and
64-bit integer types.
</p>
258 <p><b><i>Note:
</i></b> One-byte big-endian, little-endian, and native-endian types provide identical
259 functionality. All three names are provided to improve code readability and searchability.
</p>
260 <h3><a name=
"Comment-on-naming">Comment on naming
</a></h3>
261 <p>When first exposed to endian types, programmers often fit them into a mental model
262 based on the
<code><cstdint
></code> types. Using that model, it is natural to
263 expect a
56-bit big-endian signed integer to be named
<code>int_big56_t
</code>
264 rather than
<code>big56_t
</code>.
</p>
265 <p>As experience using these type grows, the realization creeps in that they are
266 lousy arithmetic integers - they are really byte holders that for convenience
267 support arithmetic operations - and that for use in internal interfaces or
268 anything more than trivial arithmetic computations it is far better to convert
269 values of these endian types to traditional integer types.
</p>
270 <p>That seems to lead to formation of a new mental model specific to endian byte-holder types. In that model, the endianness
271 is the key feature, and the integer aspect is downplayed.
272 Once that mental transition is made, a name like
<code>big56_t
</code> is a good
273 reflection of the mental model
</p>
274 <h2><a name=
"Class_template_endian">Class template
<code>endian
</code></a></h2>
275 <p>An endian is an integer byte-holder with user-specified
<a href=
"#endianness">
276 endianness
</a>, value type, size, and
<a href=
"#alignment">alignment
</a>. The
277 usual operations on integers are supplied.
</p>
278 <h3><a name=
"Synopsis">Synopsis
</a></h3>
284 enum class
<a name=
"endianness">endianness
</a> { big, little, native }; // scoped enum emulated on C++
03
285 enum class
<a name=
"alignment">alignment
</a> { unaligned, aligned }; // scoped enum emulated on C++
03
287 template
<endianness E, typename T, std::size_t n_bits,
288 alignment A = alignment::unaligned
>
289 class endian :
<a href=
"../../../boost/integer/cover_operators.hpp">integer_cover_operators
</a>< endian
<E, T, n_bits, A
>, T
>
292 typedef T value_type;
293 <a href=
"#endian">endian
</a>() = default; // = default replaced by {} on C++
03
294 explicit
<a href=
"#explicit-endian">endian
</a>(T v);
295 endian
& <a href=
"#operator-eq">operator=
</a>(T v);
296 <a href=
"#operator-T">operator T
</a>() const;
299 // unaligned big endian signed integer types
300 typedef endian
< endianness::big, int_least8_t,
8 > big8_t;
301 typedef endian
< endianness::big, int_least16_t,
16 > big16_t;
302 typedef endian
< endianness::big, int_least32_t,
24 > big24_t;
303 typedef endian
< endianness::big, int_least32_t,
32 > big32_t;
304 typedef endian
< endianness::big, int_least64_t,
40 > big40_t;
305 typedef endian
< endianness::big, int_least64_t,
48 > big48_t;
306 typedef endian
< endianness::big, int_least64_t,
56 > big56_t;
307 typedef endian
< endianness::big, int_least64_t,
64 > big64_t;
309 // unaligned big endian unsigned integer types
310 typedef endian
< endianness::big, uint_least8_t,
8 > ubig8_t;
311 typedef endian
< endianness::big, uint_least16_t,
16 > ubig16_t;
312 typedef endian
< endianness::big, uint_least32_t,
24 > ubig24_t;
313 typedef endian
< endianness::big, uint_least32_t,
32 > ubig32_t;
314 typedef endian
< endianness::big, uint_least64_t,
40 > ubig40_t;
315 typedef endian
< endianness::big, uint_least64_t,
48 > ubig48_t;
316 typedef endian
< endianness::big, uint_least64_t,
56 > ubig56_t;
317 typedef endian
< endianness::big, uint_least64_t,
64 > ubig64_t;
319 // unaligned little endian signed integer types
320 typedef endian
< endianness::little, int_least8_t,
8 > little8_t;
321 typedef endian
< endianness::little, int_least16_t,
16 > little16_t;
322 typedef endian
< endianness::little, int_least32_t,
24 > little24_t;
323 typedef endian
< endianness::little, int_least32_t,
32 > little32_t;
324 typedef endian
< endianness::little, int_least64_t,
40 > little40_t;
325 typedef endian
< endianness::little, int_least64_t,
48 > little48_t;
326 typedef endian
< endianness::little, int_least64_t,
56 > little56_t;
327 typedef endian
< endianness::little, int_least64_t,
64 > little64_t;
329 // unaligned little endian unsigned integer types
330 typedef endian
< endianness::little, uint_least8_t,
8 > ulittle8_t;
331 typedef endian
< endianness::little, uint_least16_t,
16 > ulittle16_t;
332 typedef endian
< endianness::little, uint_least32_t,
24 > ulittle24_t;
333 typedef endian
< endianness::little, uint_least32_t,
32 > ulittle32_t;
334 typedef endian
< endianness::little, uint_least64_t,
40 > ulittle40_t;
335 typedef endian
< endianness::little, uint_least64_t,
48 > ulittle48_t;
336 typedef endian
< endianness::little, uint_least64_t,
56 > ulittle56_t;
337 typedef endian
< endianness::little, uint_least64_t,
64 > ulittle64_t;
339 // unaligned native endian signed integer types
340 typedef endian
< endianness::native, int_least8_t,
8 > native8_t;
341 typedef endian
< endianness::native, int_least16_t,
16 > native16_t;
342 typedef endian
< endianness::native, int_least32_t,
24 > native24_t;
343 typedef endian
< endianness::native, int_least32_t,
32 > native32_t;
344 typedef endian
< endianness::native, int_least64_t,
40 > native40_t;
345 typedef endian
< endianness::native, int_least64_t,
48 > native48_t;
346 typedef endian
< endianness::native, int_least64_t,
56 > native56_t;
347 typedef endian
< endianness::native, int_least64_t,
64 > native64_t;
349 // unaligned native endian unsigned integer types
350 typedef endian
< endianness::native, uint_least8_t,
8 > unative8_t;
351 typedef endian
< endianness::native, uint_least16_t,
16 > unative16_t;
352 typedef endian
< endianness::native, uint_least32_t,
24 > unative24_t;
353 typedef endian
< endianness::native, uint_least32_t,
32 > unative32_t;
354 typedef endian
< endianness::native, uint_least64_t,
40 > unative40_t;
355 typedef endian
< endianness::native, uint_least64_t,
48 > unative48_t;
356 typedef endian
< endianness::native, uint_least64_t,
56 > unative56_t;
357 typedef endian
< endianness::native, uint_least64_t,
64 > unative64_t;
359 // These types only present if platform has exact size integers:
361 // aligned big endian signed integer types
362 typedef endian
< endianness::big, int16_t,
16, alignment::aligned
> aligned_big16_t;
363 typedef endian
< endianness::big, int32_t,
32, alignment::aligned
> aligned_big32_t;
364 typedef endian
< endianness::big, int64_t,
64, alignment::aligned
> aligned_big64_t;
366 // aligned big endian unsigned integer types
367 typedef endian
< endianness::big, uint16_t,
16, alignment::aligned
> aligned_ubig16_t;
368 typedef endian
< endianness::big, uint32_t,
32, alignment::aligned
> aligned_ubig32_t;
369 typedef endian
< endianness::big, uint64_t,
64, alignment::aligned
> aligned_ubig64_t;
371 // aligned little endian signed integer types
372 typedef endian
< endianness::little, int16_t,
16, alignment::aligned
> aligned_little2_t;
373 typedef endian
< endianness::little, int32_t,
32, alignment::aligned
> aligned_little4_t;
374 typedef endian
< endianness::little, int64_t,
64, alignment::aligned
> aligned_little8_t;
376 // aligned little endian unsigned integer types
377 typedef endian
< endianness::little, uint16_t,
16, alignment::aligned
> aligned_ulittle2_t;
378 typedef endian
< endianness::little, uint32_t,
32, alignment::aligned
> aligned_ulittle4_t;
379 typedef endian
< endianness::little, uint64_t,
64, alignment::aligned
> aligned_ulittle8_t;
382 // aligned native endian typedefs are not provided because
383 //
<cstdint
> types are superior for this use case
385 } // namespace integer
386 } // namespace boost
</pre>
387 <h3><a name=
"Members">Members
</a></h3>
388 <p><code><a name=
"endian">endian
</a>() = default;
// C++
03: endian(){}
</code></p>
390 <p><i>Effects:
</i> Constructs an object of type
<code>endian
<E, T, n_bits, A
></code>.
</p>
392 <p><code><a name=
"explicit-endian">explicit endian
</a>(T v);
</code></p>
394 <p><i>Effects:
</i> Constructs an object of type
<code>endian
<E, T, n_bits, A
></code>.
</p>
395 <p><i>Postcondition:
</i> <code>x == v,
</code> where
<code>x
</code> is the
396 constructed object.
</p>
398 <p><code>endian
& <a name=
"operator-eq">operator=
</a>(T v);
</code></p>
400 <p><i>Postcondition:
</i> <code>x == v,
</code> where
<code>x
</code> is the
401 constructed object.
</p>
402 <p><i>Returns:
</i> <code>*this
</code>.
</p>
404 <p><code><a name=
"operator-T">operator T
</a>() const;
</code></p>
406 <p><i>Returns:
</i> The current value stored in
<code>*this
</code>, converted to
407 <code>value_type
</code>.
</p>
409 <h3>Other operators
</h3>
410 <p>Other operators on endian objects are forwarded to the equivalent
411 operator on
<code>value_type
</code>.
</p>
412 <h2><a name=
"FAQ">FAQ
</a></h2>
413 <p><b>Why bother with endian types?
</b> External data portability and both speed
414 and space efficiency. Availability
415 of additional binary integer sizes and alignments is important in some
417 <p><b>Why not just use Boost.Serialization?
</b> Serialization involves a
418 conversion for every object involved in I/O. Endian objects require no
419 conversion or copying. They are already in the desired format for binary I/O.
420 Thus they can be read or written in bulk.
</p>
421 <p><b>Why bother with binary I/O? Why not just use C++ Standard Library stream
422 inserters and extractors?
</b> Using binary rather than character representations
423 can be more space efficient, with a side benefit of faster I/O. CPU time is
424 minimized because conversions to and from string are eliminated.
425 Furthermore, binary integers are fixed size, and so fixed-size disk records
426 are possible, easing sorting and allowing direct access. Disadvantages, such as the inability to use
427 text utilities on the resulting files, limit usefulness to applications where
429 binary I/O advantages are paramount.
</p>
430 <p><b>Do these types have any uses outside of I/O?
</b> Probably not, except for
431 native endianness which can be used for fine grained control over size and
433 <p><b>Is there is a performance hit when doing arithmetic using these types?
</b> Yes, for sure,
434 compared to arithmetic operations on native integer types. However, these types
435 are usually be faster, and sometimes much faster, for I/O compared to stream
436 inserters and extractors, or to serialization.
</p>
437 <p><b>Are endian types POD's?
</b> Yes for C++
0x. No for C++
03, although several
438 <a href=
"#Compilation">macros
</a> are available to force PODness in all cases.
</p>
439 <p><b>What are the implications endian types not being POD's of C++
03?
</b> They
440 can't be used in unions. In theory, compilers aren't required to align or lay
441 out storage in portable ways, although this problem has never been observed in a
443 <p><b>Which is better, big-endian or little-endian?
</b> Big-endian tends to be a
444 bit more of an industry standard, but little-endian may be preferred for
445 applications that run primarily on x86 (Intel/AMD) and other little-endian
446 CPU's. The
<a href=
"http://en.wikipedia.org/wiki/Endian">Wikipedia
</a> article
447 gives more pros and cons.
</p>
448 <p><b>What good is
<i>native
</i>endianness?
</b> It provides alignment and
449 size guarantees not available from the built-in types. It eases generic
451 <p><b>Why bother with the aligned endian types?
</b> Aligned integer operations
452 may be faster (
20 times, in one measurement) if the endianness and alignment of
453 the type matches the endianness and alignment requirements of the machine. On
454 common CPU architectures, that optimization is only available for aligned types.
455 That allows I/O of maximally efficient types on an application's primary
456 platform, yet produces data files are portable to all platforms. The code,
458 likely to be more fragile and less portable than with the unaligned types.
</p>
459 <p><b>These types are really just byte-holders. Why provide the arithmetic
460 operations at all?
</b> Providing a full set of operations reduces program
461 clutter and makes code both easier to write and to read. Consider
462 incrementing a variable in a record. It is very convenient to write:
</p>
463 <pre wrap
> ++record.foo;
</pre>
464 <p wrap
>Rather than:
</p>
465 <pre wrap
> int temp( record.foo);
467 record.foo = temp;
</pre>
468 <p wrap
><b>Why do binary stream insertion and extraction use operators
<= and
>=
469 rather than
<<= and
>>=?
</b> <<= and
>>= associate right-to-left, which is the
470 opposite of
<< and
>>, so would be very confusing and error prone.
<= and
>=
471 associate left-to-right.
</p>
472 <h2><a name=
"Binary-I-O-cautions">Binary I/O warnings and cautions
</a></h2>
473 <p><font color=
"#FF0000"><b><i><span style=
"background-color: #FFFFFF">Warning:
</span></i></b></font><span style=
"background-color: #FFFFFF"> </span> Use
474 only on streams opened with filemode
<code>std::ios_base::binary
</code>. Thus
475 unformatted binary I/O should not be with the standard streams (cout, cin, etc.)
476 since they are opened in text mode. Use on text streams may produce incorrect
477 results, such as insertion of unwanted characters or premature end-of-file. For
478 example, on Windows
0x0D would become
0x0D,
0x0A.
</p>
479 <p><i><b><font color=
"#FF0000">Caution:
</font><font color=
"#FFFF00"> </font></b>
480 </i>When mixing formatted (i.e. operator
<< or
>>) and unformatted (i.e.
481 operator
<= or
>=) stream I/O, be aware that
<< and
>> take precedence over
<=
482 and
>=. Use parentheses to force correct order of evaluation. For example:
</p>
484 <pre>my_stream
<< foo
<= bar; // no parentheses needed
485 (my_stream
<= foo)
<< bar; // parentheses required
</pre>
487 <p>As a practical matter, it may be easier and safer to never mix the character
488 and binary insertion or extraction operators in the same statement.
</p>
489 <h2><a name=
"Example">Example
</a></h2>
490 <p>The
<a href=
"../example/endian_example.cpp">endian_example.cpp
</a> program writes a
491 binary file containing four byte big-endian and little-endian integers:
</p>
493 <pre>#include
<iostream
>
494 #include
<cassert
>
495 #include
<cstdio
>
496 #include
<boost/integer/endian.hpp
>
498 using namespace boost::integer;
502 // This is an extract from a very widely used GIS file format. I have no idea
503 // why a designer would mix big and little endians in the same file - but
504 // this is a real-world format and users wishing to write low level code
505 // manipulating these files have to deal with the mixed endianness.
512 little32_t shape_type;
515 const char * filename =
"test.dat
";
520 assert( sizeof( header ) ==
16 ); // requirement for interoperability
524 h.file_code =
0x04030201;
525 h.file_length = sizeof( header );
527 h.shape_type =
0x04030201;
529 // Low-level I/O such as POSIX read/write or
<cstdio
> fread/fwrite is sometimes
530 // used for binary file operations when ultimate efficiency is important.
531 // Such I/O is often performed in some C++ wrapper class, but to drive home the
532 // point that endian integers are often used in fairly low-level code that
533 // does bulk I/O operations,
<cstdio
> fopen/fwrite is used for I/O in this example.
537 if ( !(fi = std::fopen( filename,
"wb
" )) ) // MUST BE BINARY
539 std::cout
<< "could not open
" << filename
<< '\n';
543 if ( std::fwrite(
&h, sizeof( header ),
1, fi ) !=
1 )
545 std::cout
<< "write failure for
" << filename
<< '\n';
551 std::cout
<< "created file
" << filename
<< '\n';
555 <p>After compiling and executing
<a href=
"endian_example.cpp">endian_example.cpp
</a>, a hex dump of
<code>test.dat
</code> shows:
</p>
557 <pre>0403 0201 0000 0010 ffff ffff
0102 0304</pre>
559 <h2><a name=
"Design">Design
</a> considerations for Boost.Endian
</h2>
561 <li>Must be suitable for I/O - in other words, must be memcpyable.
</li>
562 <li>Must provide exactly the size and internal byte ordering specified.
</li>
563 <li>Must work correctly when the internal integer representation has more bits
564 that the sum of the bits in the external byte representation. Sign extension
565 must work correctly when the internal integer representation type has more
566 bits than the sum of the bits in the external bytes. For example, using
567 a
64-bit integer internally to represent
40-bit (
5 byte) numbers must work for
568 both positive and negative values.
</li>
569 <li>Must work correctly (including using the same defined external
570 representation) regardless of whether a compiler treats char as signed or
572 <li>Unaligned types must not cause compilers to insert padding bytes.
</li>
573 <li>The implementation should supply optimizations only in very limited
574 circumstances. Experience has shown that optimizations of endian
575 integers often become pessimizations. While this may be obvious when changing
576 machines or compilers, it also happens when changing compiler switches,
577 compiler versions, or CPU models of the same architecture.
</li>
578 <li>It is better software engineering if the same implementation works regardless
579 of the CPU endianness. In other words, #ifdefs should be avoided where
582 <h2><a name=
"Experience">Experience
</a></h2>
583 <p>Classes with similar functionality have been independently developed by
584 several Boost programmers and used very successful in high-value, high-use
585 applications for many years. These independently developed endian libraries
586 often evolved from C libraries that were also widely used. Endian integers have proven widely useful across a wide
587 range of computer architectures and applications.
</p>
588 <h2><a name=
"C++0x">C++
0x
</a></h2>
589 <p>The availability of the C++
0x
590 <a href=
"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">
591 Defaulted Functions
</a> feature is detected automatically, and will be used if
592 present to ensure that objects of
<code>class endian
</code> are trivial, and
594 <h2><a name=
"Compilation">Compilation
</a></h2>
595 <p>Boost.Endian is implemented entirely within headers, with no need to link to
596 any Boost object libraries.
</p>
597 <p>Several macros allow user control over features:
</p>
599 <li>BOOST_ENDIAN_NO_CTORS causes
<code>class endian
</code> to have no
600 constructors. The intended use is for compiling user code that must be
601 portable between compilers regardless of C++
0x
602 <a href=
"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">
603 Defaulted Functions
</a> support. Use of constructors will always fail,
<br>
605 <li>BOOST_ENDIAN_FORCE_PODNESS causes BOOST_ENDIAN_NO_CTORS to be defined if
606 the compiler does not support C++
0x
607 <a href=
"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">
608 Defaulted Functions
</a>. This is ensures that , and so can be used in unions.
609 In C++
0x,
<code>class endian
</code> objects are POD's even though they have
612 <h2><a name=
"Acknowledgements">Acknowledgements
</a></h2>
613 <p>Original design developed by Darin Adler based on classes developed by Mark
614 Borgerding. Four original class templates combined into a single
<code>endian
</code>
615 class template by Beman Dawes, who put the library together, provided
616 documentation, and added the typedefs. He also added the
<code>unrolled_byte_loops
</code>
617 sign partial specialization to correctly extend the sign when cover integer size
618 differs from endian representation size.
</p>
619 <p>Comments and suggestions were
622 Christopher Kohlhoff,
638 <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->19 March,
2009<!--webbot bot="Timestamp" endspan i-checksum="29039" --></p>
639 <p>© Copyright Beman Dawes,
2006-
2009</p>
640 <p>Distributed under the Boost Software License, Version
1.0. (See accompanying
641 file
<a href=
"../../../LICENSE_1_0.txt">LICENSE_1_0.txt
</a> or copy at
642 <a href=
"http://www.boost.org/LICENSE_1_0.txt">www.boost.org/ LICENSE_1_0.txt
</a>)
</p>