Types Of Variables in C programming – Basics of computer programming – Free Study Material


A variable’s type (or data type) is the characterization of the data that it represents.A computer only “speaks” in 0s and 1s (binary). A variable is merely a memory location in which a series of 0s and 1s is stored. That binary string could represent a number (either an integer or a floating point number), a single alphanumeric character or series of characters (string), a Boolean type or some other, more complex user-defined type.

The type of a variable is important because it affects how the raw binary data stored at a memory location is interpreted. Moreover, some types take a different amount of memory to store. For example, an integer type could take 32 bits while a floating point type could take 64 bits. Programming languages may support different types and may do so in different ways. In the next few sections we’ll describe some common types that are supported by many languages.

Numeric Types At their most basic, computers are number crunching machines. Thus, the most basic type of variable that can be used in a computer program is a numeric type. There are several numeric types that are supported by various programming languages. The most simple is an integer type which can represent whole numbers 0, 1, 2, etc. and their negations, −1, −2, . . .. Floating point numeric types represent decimal numbers such as 0.5, 3.14, 4.0, etc. However, neither integer nor floating point numbers can represent every possible number since they use a finite number of bits to represent the number. We will examine this in detail below. For now, let’s understand how a computer represents both integers and floating point numbers in memory. As humans, we “think” in base-10 (decimal) because we have 10 fingers and 10 toes. When we write a number with multiple digits in base-10 we do so using “places” (ones place, tens place, hundreds place, etc.).

Mathematically, a number in base-10 can be broken down into powers of ten; for example:

3, 201 = 3 × 10^3 + 2 × 10^2 + 0 × 10^1 + 1 × 10^0

In general, any number in base-10 can be written as the summation of powers of 10 multiplied by numbers 0–9,

ck × 10^k + ck−1 × 10^(k−1) + · · · c1 · 10^1 + c0

In binary, numbers are represented in the same way, but in base-2 in which we only have 0 and 1 as symbols. To illustrate, let’s consider counting from 0: in base-10, we would count 0, 1, 2, . . . , 9 at which point we “carry-over” a 1 to the tens spot and start over at 0 in the ones spot, giving us 10, 11, 12, . . . , 19 and repeat the carry-over to 20. With only two symbols, the carry-over occurs much more frequently, we count 0, 1 and then carry over and have 10. It is important to understand, this is not “ten”: we are counting in base-2, so 10 is actually equivalent to 2 in base-10. Continuing, we have 11 and again carry over, but we carry it over twice giving us 100 (just like we’d carry over twice when going from 99 to 100 in base-10). A full count from 0 to 16 in binary can be found in Table 2.1. In many programming languages, a prefix of 0b is used to denote a number represented in binary. We use this convention in the table. As a fuller example, consider again the number 3,201. This can be represented in binary as follows.

0b110010000001 = 1 × 2 ^11 + 1 × 2 ^10 + 0 × 2^ 9 + 0 × 2^ 8+ 1 × 2 ^7 + 0 × 2^ 6 + 0 × 2^ 5 + 0 × 2^ 4+ 0 × 2^ 3 + 0 × 2^ 2 + 0 × 2^ 1 + 1 × 2^ 0
                    = 211 + 210 + 27 + 20
                   =2048+1,024+128+1.                                 = 3, 201

  Representing negative numbers is a bit more com- plicated and is usually done using a scheme called two’s complement. We omit the details, but essen- tially the first bit in the representation serves as a sign bit: zero indicates positive, while 1 indicates negative. Negative values are represented as a com- plement with respect to 2n (a complement is where 0s and 1s are “flipped” to 1s and 0s).

When represented using two’s complement, binary numbers with n bits can represent numbers x in the range

−2^ n−1 ≤ x ≤ 2 ^(n−1) − 1

Note that the upper bound follows from the fact that

The – 1 captures the idea that we start at zero. The exponent in the upper bound is n − 1 since we need one bit to represent the sign. The lower bound represents the idea that we have 2n−1 possible values (n − 1 since we need one bit for the sign bit) and we don’t need to start at zero, we can start at −1. Following contains ranges for common integer types using various number of bits.
Some programming languages allow you to define variables that are unsigned in which the sign bit is not used to indicate positive/negative. With the extra bit we can represent numbers twice as big; using n bits we can represent numbers x in the range
        0 ≤ x ≤ 2 n − 1

Floating point numbers in binary are represented in a manner similar to scientific notation. Recall that in scientific notation, a number is normalized by multiplying it by some power of 10 so that it its most significant digit is between 1 and 9. The resulting normalized number is called the significand while the power of ten that the number was scaled by is called the exponent (and since we are base-10, 10 is the base). In general, a number in scientific notation is represented as:

significand × base^exponent

For example,

      14326.123 = 1.4326123 x 10^4

Sometimes the notation1.4326123e+4, 1.4326123e4  or 1.4326123E are used. As before, we can see that a fractional number in base-10 can be seen as a summation of powers of 10:

1.4326123 = 1 × 10^1 + 4 × 10^−1 + 3 × 10^−2 + 2 × 10^−3+ 6 × 10^−4 + 1 × 10^−5 + 2 × 10^−6 + 3 × 10^−7

In binary, floating point numbers are represented in a similar way, but the base is 2, consequently a fractional number in binary is a summation of powers of 2. For example,

110.011 =1 × 2^ 2 + 1 × 2^ 1 + 0 × 2^ 0 + 0 × 2^ −1 + 1 × 2^ −2 + 1 × 2^ −3 =1 × 4 + 1 × 2 + 0 × 1 + 0 × 1/2 + 1 × 1/4 + 1 ×  8 =4 + 2 + 0 + 0 + 1 /4 + 1 /8 =6.375

In binary, the significand is often referred to as a mantissa. We also normalize a binary floating point number so that the mantissa is between 1 2 and 1. This is where the term floating point comes from: the decimal point (more generally called a radix point) “floats” left and right to ensure that the number is always normalized. The example above would normalized to

0.110011 × 2^3

Here, 0.110011 is the mantissa and 3 is the exponent (which in binary would be 0b11).

Most modern programming languages implement floating point numbers according to the Institute of Electrical and Electronics Engineers (IEEE) 754 Standard [20] (also called the International Electrotechnical Commission (IEC) 60559 [19]). When represented in binary, a fixed number of bits must be used to represent the sign, mantissa and exponent. The standard defines several precisions that each use a fixed number of bits with a resulting number of significant digits (base-10) of precision. Table 2.3 contains a summary of a few of the most commonly implemented precisions. Just as with integers, the finite precision of floating point numbers results in several limi- tations. First, irrational numbers such as π = 3.14159 . . . can only be approximated out to a certain number of digits. For example, with single precision π ≈ 3.1415927 which is accurate only to the 6th decimal place and with double precision, π ≈ 3.1415926535897931 approximate to only 15 decimal places.3 In fact, regardless of how many bits we allow in our representation, an irrational number like π (that never repeats and never terminates) will only ever be an approximation. Real numbers like π require an infinite precision, but computers are only finite machines. Even numbers that have a finite representation (rational numbers) such as 1 /3 = 0.333 are not represented exactly when using floating point numbers. In double precision binary,
  1/3=0b1.0101010101010101010101010101010101010101010101010101 × 2^ −2 which when represented in scientific notation in decimal is

3.3333333333333330 × 10−1

That is, there are only 16 digits of precision, after which the remaining (infinite) sequence of 3s get cut off. Programming languages usually only support the common single and double precisions defined by the IEEE 754 standard as those are commonly supported by hardware. 3The first 80 digits of π are 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899
though only 39 digits of π are required to accurately calculate the volume of the known universe to within one atom.

However, there are languages that support arbitrary precision (also called multiprecision) numbers and yet other languages that have many libraries to support “big number” arithmetic. Arbitrary precision is still not infinite: instead, as more digits are needed, more memory is allocated. If you want to compute 10 more digits of π, you can but at a cost. To support the additional digits, more memory is allocated. Also, operations are performed in software using many operations which can be much slower than performing fixed-precision arithmetic directly in hardware. Still, there are many applications where such accuracy or large numbers are absolutely essential.

Leave a Reply