Designing and Building Portable Systems in C++ - Applied Informatics
Designing and Building Portable Systems in C++ - Applied Informatics
Designing and Building Portable Systems in C++ - Applied Informatics
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
2.5 Float<strong>in</strong>g Po<strong>in</strong>t Types<br />
Similar to <strong>in</strong>teger types, the <strong>C++</strong> st<strong>and</strong>ard does not specify any particular b<strong>in</strong>ary<br />
representation for float<strong>in</strong>g po<strong>in</strong>t numbers. The st<strong>and</strong>ard def<strong>in</strong>es three float<strong>in</strong>g po<strong>in</strong>t types:<br />
float, double <strong>and</strong> long double. Type double must provide at least as much precision as<br />
float, <strong>and</strong> long double must provide at least as much precision as double. Furthermore,<br />
the set of values of the type float must be a subset of the values of type double <strong>and</strong> the set<br />
of values of the type double must be a subset of the values of type long double. Although<br />
not required by the st<strong>and</strong>ard, the implementation of float<strong>in</strong>g po<strong>in</strong>t arithmetic used by most<br />
<strong>C++</strong> compilers conforms to a st<strong>and</strong>ard, IEEE 754-1985, at least for types float <strong>and</strong> double.<br />
This is directly related to the fact that the float<strong>in</strong>g po<strong>in</strong>t units of modern CPUs also implement<br />
this st<strong>and</strong>ard. The IEEE 754 st<strong>and</strong>ard specifies the b<strong>in</strong>ary format for float<strong>in</strong>g po<strong>in</strong>t numbers,<br />
as well as the semantics for float<strong>in</strong>g po<strong>in</strong>t operations.<br />
Byte order also applies to float<strong>in</strong>g po<strong>in</strong>t types, so on a big-endian mach<strong>in</strong>e, the constant π =<br />
3.1415926... (or, strictly speak<strong>in</strong>g, an approximation of it) as a float value, will be stored as<br />
0x40 0x49 0x0F 0xDB, while on a little-endian mach<strong>in</strong>e it will be stored as 0xDB 0x0F 0x49<br />
0x40. Of all three float<strong>in</strong>g po<strong>in</strong>t types, long double is the least portable. Some systems do not<br />
support long double directly; on these systems, it is the same size as a double. Byte order<br />
issues aside, float <strong>and</strong> double values usually can be exchanged <strong>in</strong> b<strong>in</strong>ary format between<br />
platforms; long double values cannot.<br />
The IEEE 754 st<strong>and</strong>ard has some special features, <strong>and</strong> they are a major reason for problems<br />
when port<strong>in</strong>g float<strong>in</strong>g po<strong>in</strong>t code between platforms. NaN (Not a Number) is a special value<br />
represent<strong>in</strong>g the result of tak<strong>in</strong>g the square root of a negative number. Inf<strong>in</strong>ity is the result of a<br />
divide by zero. Signed zero means there are two representations for zero: +0 <strong>and</strong> –0. There are<br />
also gradual underflow <strong>and</strong> denormal numbers, but these two features are not universally<br />
available. F<strong>in</strong>ally, there are various round<strong>in</strong>g modes, float<strong>in</strong>g po<strong>in</strong>t exceptions <strong>and</strong> flags,<br />
which may be useful to some applications. <strong>C++</strong> does not provide support for work<strong>in</strong>g with<br />
these features (for example, check<strong>in</strong>g for NaN or Inf<strong>in</strong>ity), but there are usually non-st<strong>and</strong>ard<br />
functions provided by runtime libraries. Also, the C99 st<strong>and</strong>ard provides some support here.<br />
Neither the IEEE 754 nor the <strong>C++</strong> st<strong>and</strong>ard specify how transcendental functions like s<strong>in</strong>(),<br />
cos(), exp(), etc. have to be implemented. Therefore, for the same arguments, the results<br />
that these functions return on various platforms might not be the same. This is another reason<br />
for gett<strong>in</strong>g non-identical results for the same expression on different platforms. The st<strong>and</strong>ard<br />
also does not specify how the conversion from decimal float<strong>in</strong>g po<strong>in</strong>t values to their b<strong>in</strong>ary<br />
representation must be implemented.<br />
3 Operat<strong>in</strong>g System APIs<br />
Modern general-purpose operat<strong>in</strong>g systems give application <strong>and</strong> system programmers a<br />
variety of programm<strong>in</strong>g <strong>in</strong>terfaces to work with. At the lowest level, every operat<strong>in</strong>g system<br />
provides so-called system calls, system services or executive services – functions directly<br />
implemented <strong>in</strong> the operat<strong>in</strong>g system kernel, <strong>and</strong> <strong>in</strong>voked via some k<strong>in</strong>d of software <strong>in</strong>terrupt<br />
or trap mechanism. On a higher level are library functions, such as those from the C library on<br />
Unix. W<strong>in</strong>dows NT goes one step further <strong>and</strong> has so-called personalities or subsystems –<br />
different sets of programm<strong>in</strong>g <strong>in</strong>terfaces that are all implemented <strong>in</strong> terms of the low-level<br />
system services. The W<strong>in</strong>32 API is not, as one might easily guess, the native programm<strong>in</strong>g<br />
<strong>in</strong>terface of W<strong>in</strong>dows NT, but rather a higher-level API built atop the largely undocumented<br />
executive services.<br />
9