Previous section   Next section

Imperfect C++ Practical Solutions for Real-Life Programming
By Matthew Wilson
Table of Contents
Chapter 13.  Fundamental Types


13.3. Large Integer Types

The built-in integer types provided by C/C++ are often entirely sufficient for one's programming needs. However, as machine architectures and disk sizes have grown, the need for larger integer types has grown. A 32-bit signed integer has a range of –2,147,483,648 => 2,147,483,647, an unsigned one of 0 => 4,294,967,295. So a 32-bit number can represent, say, a file offset only if the maximum size of the file is ~4GB. On 64-bit operating systems, it is essential to have 64-bit types to represent the full-sized data word, as well as to represent pointers that can manipulate a 64-bit address space. Modern C/C++ compilers provide 64-bit integers, and while there is currently an inconvenient lack of standardization—some provide the C99 standard long long type, others __int64—it is pretty straightforward to harness the preprocessor to create compiler-independent typedefs, for example, int64_t.

But sometimes we want larger types than those provided by our compilers.

If the requirement is for arbitrarily large integer types, then this is something that should be provided by a library [Hans1997], as some other languages, such as Python and Ruby, do. Such types are very flexible, but representation and manipulation use complex, and comparatively slow, techniques.

Some applications require large fixed integer types, for example, cryptographic analysis. If we need more than 64 bits, or we're dealing with compilers that don't have 64-bit integers,[6] we do not have the support of the language?

[6] I know of no modern (32-bit) compilers that do not provide 64-bit integers, but it's possible.

Imperfection: C/C++ do not provide large fixed-sized integer types.


In and of itself, this is not really a serious flaw, since the demand for such types is reasonably low, and the minimum acceptable range of fixed-sized types would always be a matter for subjective debate. You can sear your eyeballs just imagining the flame wars. Furthermore, the difficulties of providing integer arithmetic without direct support from the processor hardware are nontrivial. Walter Bright, author of the Digital Mars C/C++/D compilers, states [WB-Email], "To do it inefficiently is pretty simple: just turn it into BCD[, but to] do it efficiently requires dealing with the Carry flag, which is not accessible from [C/C++]. Hence it would need to be done with assembler."

Just as with arbitrarily large types, the answer for C++ (and C) is to create user defined types that represent such types. Indeed, one of C++'s most powerful features is the fact that it supports the definition of user-defined types.

The natural technique to adopt is to define a structure that contains suitable fundamental integers, such as the uinteger64 type we saw in section 4.4 and its signed equivalent:



struct integer64


{


  uint32_t  lowerVal;


  int32_t   upperVal;


};





struct uinteger64


{


  uint32_t  lowerVal;


  uint32_t  upperVal;


};



As we saw in section 4.4, using such types is anything but straightforward. They lack encapsulation (see section 4.5), since lowerVal and upperVal can be manipulated independently in client code. They are not value types (see section 4.6) since the following is not supported:



integer64 i1;


integer64 i2;





if(i1 == i2) // Error – integer64 does not define this operator


{



They do not support the natural syntax and semantics (see section 4.7) of integers:



integer64 i2 = i1 + i2; // Error. integer64 does not define this operator



We're going to study the uinteger64 type, and how it can be made to support the syntax and semantics of arithmetic value types (see section 4.7) in detail in Chapter 29. As we'll see, C++ allows us to transform it into a near-perfect 64-bit user defined type. But it is the "near" aspect of this transformation that represents the real imperfection and validates the imperfection presented earlier.


      Previous section   Next section