Reader small image

You're reading from  Learn C Programming. - Second Edition

Product typeBook
Published inAug 2022
PublisherPackt
ISBN-139781801078450
Edition2nd Edition
Right arrow
Author (1)
Jeff Szuhay
Jeff Szuhay
author image
Jeff Szuhay

Jeff Szuhay is the principal developer at QuarterTil2 which specializes in graphics-rich software chronographs for desktop environments. In his software career of over 35 years, he has engaged in a full range of development activities from systems analysis and systems performance tuning to application design, from initial development through full testing and final delivery. Throughout that time, he has taught computer applications and programming languages at various educational levels from elementary school students to university students, as well as developed and presented professional, on-site training.
Read more about Jeff Szuhay

Right arrow

Chapter 3: Working with Basic Data Types

Everything in a computer is a sequence of binary digits. C's basic data types enable the compiler to tell the computer how to interpret binary sequences of data. Intrinsic data types are predefined and built into the language.

A binary sequence plus a data type results in a meaningful value. The data type not only leads to a meaningful value, but it also helps you determine what kind of operations on that value make sense. Operations involve manipulating values along with converting or casting a value from one data type into a related data type.

In this chapter, we will cover the following topics:

  • Understanding bytes and chunks of data
  • Working with whole numbers
  • Representing numbers with fractions
  • Representing single characters
  • Understanding false (or zero) versus true (or anything not exactly zero)
  • Understanding how types are implemented on your computer with sizeof()
  • Discovering the minimum and maximum...

Technical requirements

For the remainder of this book, unless otherwise stated, you will continue to use your computer with the following:

  • A plain text editor of your choice
  • A console, Terminal, or command-line window (depending on your OS)
  • The compiler, either GCC or Clang, for your particular OS

For the sake of consistency, it is best if you use the same computer and programming tools. By doing so, you can focus more closely on the details of C on your computer.

The source code for this chapter can be found at https://github.com/PacktPublishing/Learn-C-Programming-Second-Edition/tree/main/Chapter03.

Understanding data types

Everything in a computer is a sequence of binary digits (or bits). A single bit is either off (0) or on (1). Eight bits are strung together to form a byte. A byte is the basic unit of data. Bytes are treated singly, as pairs called 16-bit words, as quadruples to form 32-bit words, or as octets to form 64-bit words. These combinations of sizes of bytes are used in the following ways:

  • As instructions for the CPU
  • As addresses for the locations of all things in the computer
  • As data values

The compiler generates binary instructions from our C statements; therefore, we don't need to deal with these binary instructions since we are writing proper C syntax.

Additionally, we interact with various parts of the computer via the address of that part. Typically, we don't do this directly. For instance, we've discussed how printf() knows how to fetch the data from a function call we make and then move it to the part of the computer...

Bytes and chunks of data

The smallest data value in C is a bit. However, bit operations tend to be very expensive and not all that common for most computer problems. In this book, we will not go into bit operations. If you find you need to delve deeper into bit operations in C, please refer to the annotated bibliography in the Appendix for texts that treat this subject more fully.

The basic data value in C is a byte or a sequence of 8 bits. The set of values a byte can represent is 256 or 28 values. These values range from 0 to 255 or 28–1. 0 is a value that must be represented in the set of 256 values; we can't leave that value out. A byte can either represent a positive integer ranging from 0 to 255, or 28–1, or a negative integer ranging from -128 to 127. In either case, there are only 256 unique combinations of 1s and 0s.

While, in our daily routine, most humans don't ordinarily count this high, for a computer, this is a very narrow range of values...

Representing whole numbers

The basic whole number type is an integer or just int. Integers can either be positive only, called unsigned, or they can be negative and positive, called signed. As you might expect, the natural use for integers is to count things. You must specify unsigned if you know you will not require negative values.

To be explicit, the default type is signed int, where the signed keyword is optional.

An unsigned integer has 0 as its lowest value; its highest value is when all bits are set to 1. For instance, a single byte value has a possible 256 values, but their range is 0 to 255. This is sometimes called the one-off problem where the starting value for counting is 0 and not 1, as we were taught when we first learned to count. This is a problem because it takes some time for new programmers to adjust their thinking. Until you are comfortable about thinking in this way, the one-off problem will be a common source of confusion and possibly the cause of bugs...

Representing numbers with fractions

Not everything in the world is a whole number. For that, we have numbers with fractions or rational numbers. Rational numbers, represented as p/q where p is the numerator and q is the denominator, are most naturally used to measure things.

A rational number is represented on the computer with the following form:

significand x baseexponent

Here, both the significand and the exponent are signed integers, and the base depends upon the floating-point implementation. The size of each depends on the number of bytes for a given rational number type. There are no unsigned components. This provides a very large range of numbers, from positive to negative, as well as very small fractional values:

Typically, when real numbers are used, either very precise values are desired or the calculations tend to have incredibly large ranges.

Historical Note

Before C23, the floating-point library was implemented with a base 2...

Representing single characters

To specify a single character, use char. Typically, the signed char and unsigned char types are not used for single characters but to represent small integer values. C was developed in the time before Unicode and UTF-8. The character set they decided to use was ASCII. All of the necessary characters for printing control, device control, and printable characters and punctuation could be represented in 7 bits.

One reason ASCII was chosen was because of its somewhat logical ordering of uppercase and lowercase letters. An uppercase A and lowercase a are different by only 1 bit. This makes it relatively easy to convert from uppercase into lowercase and vice versa. There is an ASCII table provided for your reference in the Appendix; we also develop a program to print a complete ASCII table in Chapter 15, Working with Strings.

To summarize ASCII's organization, please refer to the following table:

As Unicode, and later...

Representing Boolean true/false

A Boolean value is one that evaluates to true or false. On some systems, YES and yes are equivalent to true, while NO and no are equivalent to false. For instance, Is today Wednesday? evaluates to true only 1 out of 7 days. On the other 6 days, it evaluates to false.

Before C99, there was no explicit type for a Boolean. A value of any type that is 0 (exactly 0) is considered as also evaluating to a Boolean false. Any value other than exactly 0 (a bit pattern of only 0s) will evaluate to a Boolean value of true. Real numbers rarely, if ever, evaluate exactly to 0, especially after any kind of operation on them. Therefore, these data types would almost always evaluate to true and, hence, would be poor choices as a Boolean substitute.

Since C99, a _Bool type was added, which, when evaluated, will always evaluate to only 0 or 1. When we include the stdbool.h file, we are able to use the bool type as well; this is a bit cleaner than using the cumbersome...

Understanding the sizes of data types

As discussed earlier, the number of bytes that a type uses is directly related to the range of values it can hold. Up to this point, this has all been necessarily theoretical. Now, let's write a program to demonstrate what we've been exploring.

While we are focusing exclusively on the C standard, we need to be aware that the standard allows for quite a bit of discretion on the part of any compiler implementor. This is necessary because not all CPUs have the same architecture, nor do they all have the same capabilities. Nor should they. Also, compilers are implemented by humans trying to interpret complex standards documents. Humans, despite our best intentions, might not perfectly conform to the standard.

In this light, it is critical to understand the behavior of your compiler on your system. Here and throughout the book, we emphasize the trust but verify principle so that we are not surprised when things do not work as we expect...

Summary

Again, whew!

In this chapter, there were a lot of details about data types, chunk sizes, and value ranges. The key idea from this chapter is to remember that there are only really five data types: integers, real numbers, characters, Booleans, and pointers. Additionally, characters and Booleans can be considered special cases of integers. The fifth type, the pointer, is really just another special case of an integer, but with some specialized operations and implicit behavior.

In the next chapter, we will explore how to use these different types of values when we create and assign values.

Questions

  1. Identify the four intrinsic types we have encountered (ignore the fifth type, pointers, for now).
  2. For each of the four intrinsic types, identify each sub-type.
  3. Why is the size of a data type important?
lock icon
The rest of the chapter is locked
You have been reading a chapter from
Learn C Programming. - Second Edition
Published in: Aug 2022Publisher: PacktISBN-13: 9781801078450
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Author (1)

author image
Jeff Szuhay

Jeff Szuhay is the principal developer at QuarterTil2 which specializes in graphics-rich software chronographs for desktop environments. In his software career of over 35 years, he has engaged in a full range of development activities from systems analysis and systems performance tuning to application design, from initial development through full testing and final delivery. Throughout that time, he has taught computer applications and programming languages at various educational levels from elementary school students to university students, as well as developed and presented professional, on-site training.
Read more about Jeff Szuhay