Types

I l @ ve RuBoard

Types

C9X adds two new types in response to technology growth. Also, it increases support for type portability. That is, it offers portable ways to deal with, say, int being different sizes on different platforms.

New Types

C9X adds the long long and unsigned long long types to the C language. As 64-bit processors begin to move into the mainstream and as storage devices with larger capacities become available, the long type, with its guaranteed 32-bit minimum capacity, may no longer be adequate. The long long and unsigned long long types have the means to store 64-bit values.

Extended Integers: Portable Types

Suppose you have a program that needs a 32-bit integer type. On some systems, int will work, but on others, it won't. The long type is guaranteed to be at least 32 bits, but that raises the possibility it might be even more than 32 bits. What can you do? You could try to emulate how C handles the return time for the sizeof operator. C, recall, uses a typedef to define size_t as the appropriate integer type for a system. You could do something like this:

 typedef int int32bit; 

Your program could then use the int32bit type instead of int . If you moved to a system that needed a different type, you could just change the typdef statement and recompile.

C9X proposes a header file, inttypes.h , that takes precisely this approach, using typedef to create names that identify types with precise properties. These types are termed extended integers .

Exact Width Types

One set of typedef s identify types with precise sizes. Table H.1 lists the names and sizes. Note, however, that not all systems may be able to support all the types. For instance, there could be a system for which the smallest usable memory size is 16 bits; such a system would not support the int8_t or uint8_t types.

Table  8.1. Exact width types.
typedef Name Properties
int8_t 8 bits signed
int16_t 16 bits signed
int32_t 32 bits signed
int64_t 64 bits signed
uint8_t 8 bits unsigned
uint16_t 16 bits unsigned
uint32_t 32 bits unsigned
uint64_t 64 bits unsigned
Minimum Width Types

The minimum width types guarantee a type that is at least a certain number of bits in size. Table H.2 lists the minimum width types. These types always exist. For instance, a system that does not support 8-bit units could define int_least_8 as a 16-bit type.

Table  8.2. Minimum width types.
typedef Name Properties
int_least8_t At least 8 bits signed
int_least16_t At least 16 bits signed
int_least32_t At least 32 bits signed
int_least64_t At least 64 bits signed
uint_least8_t At least 8 bits unsigned
uint_least16_t At least 16 bits unsigned
uint_least32_t At least 32 bits unsigned
uint_least64_t At least 64 bits unsigned
Fastest Minimum Width Types

For a particular system, some integer representations can be faster than others. For example, int_least16_t might be implemented as short , but the system might do arithmetic faster using type int . So inttypes.h also defines the fastest type for representing at least a certain number of bits. Table H.3 lists the fastest minimum width types. These types always exist. In some cases, there might be no clear-cut choice for fastest; in that case, the system simply specifies one of the choices.

Table  8.3. Fastest minimum width types.
typedef Name Properties
int_fast8_t At least 8 bits signed
int_fast16_t At least 16 bits signed
int_fast32_t At least 32 bits signed
int_fast64_t At least 64 bits signed
uint_fast8_t At least 8 bits unsigned
uint_fast16_t At least 16 bits unsigned
uint_fast32_t At least 32 bits unsigned
uint_fast64_t At least 64 bits unsigned
Maximum Width Types

The inttypes.h header file also defines maximum width types. A variable of this type can hold any integer value possible for the system, taking the sign into account. Table H.4 lists the types.

Table  8.4. Maximum width types.
typedef Name Properties
intmax_t The widest signed type
uintmax_t The widest unsigned type
Integers That Can Hold Pointer Values

The inttypes.h header file also has two integer types, listed in Table H.5, that can hold pointer values accurately. That is, if you assign a type void * value to one of these types, and then assign the integer type back to the pointer, no information is lost. Either or both types might not exist.

Table  8.5. Integer types for holding pointer values.
typedef Name Properties
intptr_t Signed type can hold a pointer value
uintptr_t Unsigned type can hold a pointer value
Defined Constants

Just as limits.h defines constants representing the minimum and maximum values of the fundamental C types, inttypes.h defines constants representing limiting values for the types defined in that header file. The constants are named after the type. Take the type name, replace the _t with _MIN or _MAX , and make all the characters uppercase to get the name of the constant representing the minimum or maximum value for the type. For example, the smallest value for the int32_t type is INT32_MIN , and the largest value for the uint_fast16_t type is UINT_FAST16_MAX .

Extended Integer Constants

You can indicate a long constant with the L suffix, as in 445566L . How do you indicate that a constant is type int32_t ? Use macros defined in inttypes.h . For instance, the expression INT32_C(445566) expands to a type int32_t constant. Essentially, the macro is a type cast to the underlying type, that is, to the fundamental type that represents int32_t in a particular implementation.

The macro names are formed by taking the type name, replacing the _t with _C , and making all the letters uppercase. For example, to make 1000 a type uint_least64_t constant, use the expression UINT_LEAST64_C(1000) .

Reading and Displaying Extended Integers

You can read an unsigned int value and display it by using the %u specifier , as in the following:

 unsigned int dogs; scanf("%u, &dogs); printf("I count %u dogs.\n, dogs); 

How can you handle extended integers? For instance, type uint32_t might be unsigned int , requiring the %u specifier, or it might be unsigned long , requiring the %ul specifier. Once again, inttypes.h supplies special macros to facilitate using extended types. Here's how you might use them with the uint32_t type:

 uint32_t dogs; scanf(SCNu32, &dogs); printf("I count " PRIu32 "dogs.\n", dogs); 

The macro expands to a string. For instance, .\n". might expand to the string "%ul" . C's string concatenation then combines the three strings used by .\n". into the single string "I count %ul dogs.\n" .

The name of the macro depends on whether it is for the scanf() family, in which case the macro begins with SCN , or for the printf() family, in which case the macro begins with PRI .

Next, if it is a printf() macro for a signed type, the name uses a d or i (in honor of the %d and %i specifiers). Then the macro name ends in uppercase letters and numbers based on the name of the extended type. For instance, the macro for specifying intmax_t is PRIdMAX . The macro for specifying int_fast16_t is PRIdFAST16 , and so on.

The scheme for unsigned types is similar, except that the letter following the PRI is u (for the %u specifier), o (for the %o specifier), x (for the %x specifier) or X (for the %X specifier). Therefore, to print a type uint_LEAST16_t value in base ten, use PRIuLEAST16 . To print in hex using uppercase letters, use PRIXLEAST16 .

The macros for input use the same scheme, except that you use SCN instead of PRI and there is no X specifier for input. Therefore, to read a type int_FAST32_t value, use the SCNdFAST32 macro. To read a type uint_32 value, use SCNu32 . To read a uint_32 value that is to be entered in hexadecimal format, use SCNx32 .

I l @ ve RuBoard


C++ Primer Plus
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2000
Pages: 314
Authors: Stephen Prata

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net