You are on page 1of 15

Not only the int is an int

• It would seem that the developer’s life


would be organized well enough if they had
type int to operate with integers,
type char to manipulate characters and
type float for floating-point calculations.
However, this practice has shown that such
a narrow repertoire of types may raise
some problems.
Most of the computers currently in use
store ints using 32 bits (4 bytes); this
means that we can operate the ints within
the range of [-2147483648 .. 2147483647].
It may happen that:
• we don’t need such big values; if we count sheep, it’s unlikely that
we’ll need to count two billion of them, so why waste the majority of
these 32 bits if we don’t need them;
• we need much larger values; for example, we intend to calculate the
exact number of humans living on Earth; in this case we need more
than 32 bits to represent that number;
• this brings us to another observation – after all, the number of
inhabitants on Earth will never be a negative number; it seems like a
real waste that up to half of the permissible range will never be used.
• For these reasons, the “C” language provides
some methods for defining precisely how we
intend to store large/small numbers. This allows
the compiler to allocate memory, either smaller
than usual (e.g. 16 bits instead of 32) or larger
than usual (e.g. 64 bits instead of 32). We can
also declare that we guarantee that the value
stored in the variable will be non-negative.
• In this case the width of the variable’s range
does not change, but is shifted toward the
positive numbers. This means that instead of
the range of -2,147,483,648 .. 2,147,483,647 we
get the range of 0 .. 4294967295.
• To specify our memory requirements, we can use
some additional keywords called modifiers:

• long – is used to declare that we need a wider


range of ints than the standard one;
• short – is used to determine that we need a
narrower range of ints than the standard one;
• unsigned – is used to specify that a variable is
needed only for non-negative numbers; although
it may be surprising, we can use this modifier
together with the type char; we’ll explain how
soon.
• Note that some compilers may not be able to
distinguish data of type int and long. They may be
synonyms. If you want to force the compiler to
use actual long representation for a specific
number, you can use the long long type.
• The Counter variable will use fewer
bits than the standard int (e.g., it
could be 16 bits long – in this case,
the range of the variable will be
suppressed to the range of [-32768
to 32767]) →

The word int may be omitted as all


the declarations are considered to
be specifying int by default, like this:

short Counter;
• The Ants variable will occupy more
bits than the standard int (e.g. 64
bits, so it can be used to store
numbers from the range of [-
9223372036854775808 ..
9223372036854775807] – can you
read such huge numbers? →
Note – we can again omit the
word int:
long long Ants;
• If we come to the conclusion that
a variable will never be a
negative value, we can use
the unsigned modifier →

Of course, we can omit the int as


usual:

unsigned Positive;
• We can also mix some of the modifiers
together – take a look →

We can remove the word int and the


declaration will preserve its meaning:

unsigned long long HugeNumber;


• A more modest example is here →

Its equivalent form is:

unsigned short Lambs;


• The long and short modifiers must not be used in conjunction with
the type char (why?) and (for obvious reasons) must not be used
simultaneously in a single declaration. But there’s nothing preventing
us from using the unsigned modifier with a variable of type char.
What do we get from this declaration?

Don’t forget that we’re not allowed to omit the word char. Most of
the compilers currently in use assume that the chars are stored using
8 bits (1 byte). That may be enough to store a small value such as the
number of months or even the day of the month.
• If we treat the char variable as a signed integer number, its range would be
[-128 .. 127]. If we don’t need any signed value (as in the example here → ),
its range shifts to [0 .. 255]. This may be sufficient for many applications
and may also result in significant savings in memory usage.

But we need to add an important remark. So far we’ve used integer literals,
assuming that all of them are of type int. This is generally the case, but
there are some cases when the compiler recognizes literals of type long.
This will happen if:
• a literal value goes beyond the acceptable range of type int;
• a letter L or l is appended to the literal, such as 0L or 1981l – both of these
literals are of type long.

Another float type
• The short modifier cannot be used alongside
the float, but we may use the long modifier here. It’s
assumed that type long float is a synonym for
another type named double. The variables of
type double may differ from the variables of
type float, not only in range, but also in accuracy.
• What does this mean? The data stored in a floating-
point variable has finite precision – in other words,
only a certain number of digits are precisely
stored in the variable.
For example, we expect that the value:

1111111111111111111.111111111111111111111
• will be stored by a specific type of computer as:

1111111131851653120.000000

We say that the variable saves (only) 8 precise
digits. This is within the expected accuracy of
32-bit long floats. Using a double (which is
usually 64 bits long) guarantees that the variable
will save a more significant number of digits –
about 15-17. This is where the
name double comes from – its accuracy
is doubled compared to float.
• We told you some time ago that computer
addition is not always commutative. Do you
know why? Imagine that you have to add a large
number of floating-point values – some of them
are very large, some very small (close to zero). If
a very small float value is added to another that’s
very large, the result can be quite surprising.
• Let’s go back to the previous example – we’ll
assume that our computer only saves 8 precise
digits of any float. If we add these two floats,
we’ll probably get:

11111110656.000000

as the result. The lower value simply vanished
without a trace.
• We can’t avoid these effects when we add/subtract the numbers of
type float (and of double as well, because they’re also affected by this
issue). The phenomenon described here is what we call a numerical
anomaly.

In conclusion, the “C” language does not allow the use of


the short and unsigned modifiers alongside the
types float and double.

You might also like