The short, int, long, and long long Integer Types

Computer memory consists of units called bits. (See the “Bits and Bytes” sidebar later in this chapter.) By using different numbers of bits to store values, the C++ types short, int, long, and long long can represent up to four different integer widths. It would be convenient if each type were always some particular width for all systems—for example, if short were always 16 bits, int were always 32 bits, and so on. But life is not that simple. No one choice is suitable for all computer designs. C++ offers a flexible standard with some guaranteed minimum sizes, which it takes from C. Here’s what you get:

• A short integer is at least 16 bits wide.

• An int integer is at least as big as short.

• A long integer is at least 32 bits wide and at least as big as int.

• A long long integer is at least 64 bits wide and at least as big as long.

Many systems currently use the minimum guarantee, making short 16 bits and long 32 bits. This still leaves several choices open for int. It could be 16, 24, or 32 bits in width and meet the standard. It could even be 64 bits, providing that long and long long are at least that wide. Typically, int is 16 bits (the same as short) for older IBM PC implementations and 32 bits (the same as long) for Windows XP, Windows Vista, Windows 7, Macintosh OS X, VAX, and many other minicomputer implementations. Some implementations give you a choice of how to handle int. (What does your implementation use? The next example shows you how to determine the limits for your system without your having to open a manual.) The differences between implementations for type widths can cause problems when you move a C++ program from one environment to another, including using a different compiler on the same system. But a little care, as discussed later in this chapter, can minimize those problems.

You use these type names to declare variables just as you would use int:

short score;             // creates a type short integer variable
int temperature;         // creates a type int integer variable
long position;           // creates a type long integer variable

Actually, short is short for short int and long is short for long int, but hardly anyone uses the longer forms.

The four types—int, short, long, and long long—are signed types, meaning each splits its range approximately equally between positive and negative values. For example, a 16-bit int might run from –32,768 to +32,767.

If you want to know how your system’s integers size up, you can use C++ tools to investigate type sizes with a program. First, the sizeof operator returns the size, in bytes, of a type or a variable. (An operator is a built-in language element that operates on one or more items to produce a value. For example, the addition operator, represented by +, adds two values.) Recall that the meaning of byte is implementation dependent, so a 2-byte int could be 16 bits on one system and 32 bits on another. Second, the climits header file (or, for older implementations, the limits.h header file) contains information about integer type limits. In particular, it defines symbolic names to represent different limits. For example, it defines INT_MAX as the largest possible int value and CHAR_BIT as the number of bits in a byte. Listing 3.1 demonstrates how to use these facilities. The program also illustrates initialization, which is the use of a declaration statement to assign a value to a variable.

Listing 3.1. limits.cpp


// limits.cpp -- some integer limits
#include <iostream>
#include <climits>              // use limits.h for older systems
int main()
{
    using namespace std;
    int n_int = INT_MAX;        // initialize n_int to max int value
    short n_short = SHRT_MAX;   // symbols defined in climits file
    long n_long = LONG_MAX;
    long long n_llong = LLONG_MAX;

    // sizeof operator yields size of type or of variable
    cout << "int is " << sizeof (int) << " bytes." << endl;
    cout << "short is " << sizeof n_short << " bytes." << endl;
    cout << "long is " << sizeof n_long << " bytes." << endl;
    cout << "long long is " << sizeof n_llong << " bytes." << endl;
    cout << endl;

    cout << "Maximum values:" << endl;
    cout << "int: " << n_int << endl;
    cout << "short: " << n_short << endl;
    cout << "long: " << n_long << endl;
    cout << "long long: " << n_llong << endl << endl;

    cout << "Minimum int value = " << INT_MIN << endl;
    cout << "Bits per byte = " << CHAR_BIT << endl;
    return 0;
}



Note

If your system doesn’t support the long long type, you should remove the lines using that type.


Here is sample output from the program in Listing 3.1:

int is 4 bytes.
short is 2 bytes.
long is 4 bytes.
long long is 8 bytes.

Maximum values:
int: 2147483647
short: 32767
long: 2147483647
long long: 9223372036854775807

Minimum int value = -2147483648
Bits per byte = 8

These particular values came from a system running 64-bit Windows 7.

The following sections look at the chief programming features for this program.

The sizeof Operator and the climits Header File

The sizeof operator reports that int is 4 bytes on the base system, which uses an 8-bit byte. You can apply the sizeof operator to a type name or to a variable name. When you use the sizeof operator with a type name, such as int, you enclose the name in parentheses. But when you use the operator with the name of the variable, such as n_short, parentheses are optional:

cout << "int is " << sizeof (int) << " bytes. ";
cout << "short is " << sizeof n_short << " bytes. ";

The climits header file defines symbolic constants (see the sidebar, “Symbolic Constants the Preprocessor Way,” later in this chapter) to represent type limits. As mentioned previously, INT_MAX represents the largest value type int can hold; this turned out to be 2,147,483,647 for our Windows 7 system. The compiler manufacturer provides a climits file that reflects the values appropriate to that compiler. For example, the climits file for some older systems that used a 16-bit int, defines INT_MAX to represent 32,767. Table 3.1 summarizes the symbolic constants defined in the climits file; some pertain to types you have not yet learned.

Table 3.1. Symbolic Constants from climits

Image

Initialization

Initialization combines assignment with declaration. For example, the following statement declares the n_int variable and sets it to the largest possible type int value:

int n_int = INT_MAX;

You can also use literal constants, such as 255, to initialize values. You can initialize a variable to another variable, provided that the other variable has been defined first. You can even initialize a variable to an expression, provided that all the values in the expression are known when program execution reaches the declaration:

int uncles = 5;                       // initialize uncles to 5
int aunts = uncles;                   // initialize aunts to 5
int chairs = aunts + uncles + 4;      // initialize chairs to 14

Moving the uncles declaration to the end of this list of statements would invalidate the other two initializations because then the value of uncles wouldn’t be known at the time the program tries to initialize the other variables.

The initialization syntax shown previously comes from C; C++ has an initialization syntax that is not shared with C:

int owls = 101;   // traditional C initialization, sets owls to 101
int wrens(432);   // alternative C++ syntax, set wrens to 432


Caution

If you don’t initialize a variable that is defined inside a function, the variable’s value is indeterminate. That means the value is whatever happened to be sitting at that memory location prior to the creation of the variable.


If you know what the initial value of a variable should be, initialize it. True, separating the declaring of a variable from assigning it a value can create momentary suspense:

short year;       // what could it be?
year = 1492;      // oh

But initializing the variable when you declare it protects you from forgetting to assign the value later.

Initialization with C++11

There’s another format for initialization that’s used with arrays and structures but in C++98 can also be used with single-valued variables:

int hamburgers = {24};  // set hamburgers to 24

Using a braced initializer for a single-valued variable hasn’t been particularly common, but the C++11 standard is extending it some ways. First, it can be used with or without the = sign:

int emus{7};       // set emus to 5
int rheas = {12};  // set rheas to 12

Second, the braces can be left empty, in which case the variable is initialized to 0:

int rocs = {};     // set rocs to 0
int psychics{};    // set psychics to 0

Third, it provides better protection against type conversion errors, a topic we’ll return to near the end of this chapter.

Why, you may ask with good reason, does the language need more alternatives? As odd as it may seem, the reason is to make using C++ easier for the novice. In the past, C++ has used different forms of initialization for different types, and the form used to initialize class variables was different from the form used for ordinary structures—and that, in turn, was different from the form usually used for simple variables such as we have been using. C++ added the parentheses form of initialization to make initializing ordinary variables more like initializing class variables. C++11 makes it possible to use the braces syntax (with or without the =) with all types—a universal initialization syntax. In the future, texts may introduce you to initialization using the brace forms and mention the other forms as historical oddities retained for backward compatibility.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.77.158