Tải bản đầy đủ (.pdf) (42 trang)

Tài liệu Giáo trình C++ P1 docx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (377.46 KB, 42 trang )


www.gameinstitute.com Introduction to C and C++ : Week 1: Page 1 of 42










Game Institute



































by Stan Trujillo



Week
1

Introduction to C and C++

www.gameinstitute.com Introduction to C and C++ : Week 1: Page 2 of 42






© 2001, eInstitute, Inc.

You may print one copy of this document for your own personal use.
You agree to destroy any worn copy prior to printing another. You may
not distribute this document in paper, fax, magnetic, electronic or other
telecommunications format to anyone else.















This is the companion text to the www.gameinstitute.com
course of the
same title. With minor modifications made for print formatting, it is
identical to the viewable text, but without the audio.












www.gameinstitute.com Introduction to C and C++ : Week 1: Page 3 of 42



Table of Contents

Introduction 4
Fundamentals 4
C++ Language Features 6
Development tools 7
C++ Mechanics 8
The preprocessor 9
The Compiler 10
The Linker 11
Compilation Process 11
Project files 12
Release and Debug Builds 13
Windows applications types 13
Hello World 14
Keywords 15
Code Formatting 16
Naming Conventions 17
Compile and Run 17

Comments 18
Data Types 19
The IntMult Sample 23
Functions 25
The Celcius Sample 27
Conditionals 30
Switch Statements 33
Loops 34
The Grid Sample 35
The Ascii Sample 38
More About Functions 40
Exercises 42
What’s next? 42

www.gameinstitute.com Introduction to C and C++ : Week 1: Page 4 of 42



Introduction
A GameInstitute course by Stan Trujillo

Although it certainly wasn’t always the case, there is a great deal of information on C++ available in the
form of books, courses, and tutorials. This course differs from this existing body of information in several
ways. First, as a GameInstitute course, the goal of this course is to teach C++ to programmers who intend
to pursue game programming. Unlike most C++ courses, the final assignment is not to write a student
enrollment system or a sports statistics application. Our goal is to write games, so this course strives to
build the foundation necessary for game programming.

Another way in which this course differs is that, in addition to covering language features, we’ll talk
about how these features are typically used in game programming. Some C++ features that are rarely used

in games are covered summarily, while other features those that are use in games extensively—are
covered in detail.

Finally, because games are complex applications that involve the mixing and coordination of many
different types of systems (graphics, sound, user input, etc.), and because the structure of game
applications differs significantly from the typical business or web application, we will focus on using C++
to define the game application as a whole. The alternative is to cover each topic independently, leaving
you with the task of combining all of the topics into a single application, which usually serves to frustrate
as much as to educate.

Still, before we can successfully tackle most of the larger issues that face game programmers, we must
achieve a certain level of familiarity with C++. We’ll therefore start with three lessons that focus on the
C++ language. In the latter three lessons, we’ll use this foundation to explore game programming.

Learning to program games requires an understanding of programming concepts and programming
languages. We’ll cover both in this course, but the conceptual portions are fairly brief and to the point.
This is a C++ course, and as such the primary focus is the C++ code required for game programming. The
material is therefore full of code snippets and sample programs. This code is carefully explained, and
every effort is made to keep the complexity to a minimum. Also, the important portions of the code
typically appear in bold to draw attention to the specific commands or language syntax to which the
surrounding material refers.
Fundamentals
In some ways, computers have changed radically since they were first invented. From early models,
which occupied huge rooms and yet provided far less performance and storage space than today’s Palm
Pilot, computers have gotten smaller and faster at an amazing pace. Computer languages have changed
too. During the early years of computing there was only one computer language: machine language.

The programmers that worked with these machines were working in the machine’s native tongue—a
language in which very simple instructions such as “copy”, “add”, and “multiply” were represented as
numeric codes. The data that was manipulated by these instructions was also referred to in numeric

form—either as literal numeric values, or as the memory addresses where the data was stored. The
machine language instructions, or codes, were used to manipulate the data stored at various memory
addresses, and entire programs were written in this fashion.


www.gameinstitute.com Introduction to C and C++ : Week 1: Page 5 of 42
Writing programs in machine language was both simple and complicated. It was simple because you were
working with just a handful of instructions and a slew of memory addresses at which data could be stored
and retrieved. But machine language was complicated because each program is nothing but numbers.
Some numbers represent instructions, some represent memory addresses, and some represent literal
values. As a result, writing, deciphering, and maintaining these programs was time consuming and
painstaking work. Humans just aren’t good at manipulating pages and pages of numbers.

The problem is that computers and humans speak very different languages. Forcing humans to speak the
native language of the machine, although necessary at one time, is very taxing for humans. In order to
write large, reliable, and easily upgradeable software systems, humans needed to design a better way to
communicate with the computer.

Today there are a slew of computer languages, all of which address the issue of human/machine
communication in its own way. In all cases these languages are more natural for human use due to the use
of abstraction. Even very detail-oriented languages, such as assembly language, use abstractions.
Assembly language provides human-readable names to be used for both instructions and data, abstracting
the underling numeric values. Other languages, such as Visual Basic, Java, C, and C++ also use
abstractions, but to a much higher degree.

The more abstract the language, the less the language is like machine language. Highly abstract languages
cater to the way that humans think, and not to the way that computers operate. With a modern language,
programmers don’t have manage numeric codes, but more importantly, are not limited to the commands
that the hardware provides. These languages allow new, complex instructions to be defined that are just as
easy to use as the native computer hardware instructions. Instead of being limited to commands such as

“copy”, “add”, and “multiply”, these languages can be extended to include very powerful and specific
commands such as “update database”, “fire weapons”, or “draw explosion”.

Computer hardware has gotten much, much faster. And computer languages have gotten much, much
more powerful. But, while computer hardware now provides millions of times more performance than
early hardware, it really hasn’t changed that much. It still uses very simple numeric instructions that
indicate operations such as “copy”, “add”, and “multiply”, and it still uses memory addresses to store and
retrieve data. How can languages have evolved to be so abstract when the underlying hardware remains
largely the same? The answer is that the computer now performs much more work than it used to.

With machine language, the program, or source code that the programmer wrote was exactly the same as
that which the computer executed. The source code was the program. With all other languages, the source
code is not the same as the instructions that the computer executes. Instead there is at least one step that is
required to convert source code into executable form. This is accomplished in one of two ways,
depending on the language being used.

Languages such as Java and early versions of Visual Basic, for example, are interpreted languages. This
means that in order for source code to be executed, an interpreter is required. These interpreters are
themselves programs—which are specialized to read source code and convert it into a set of operations
that are in turn executed by the hardware. Alternatively, languages such as C, C++, and modern versions
of Visual Basic are compiled languages. These languages require a program called a compiler that reads
source code and converts it into machine language.

Interpreted languages, because they require source code to be converted at runtime (at the time that
execution is to take place), is slower than the compiled equivalent. Compiled languages, by requiring that
the highly complex conversion process take place before execution, provide better runtime performance.


www.gameinstitute.com Introduction to C and C++ : Week 1: Page 6 of 42
In both cases, the computer is expected to perform extra steps to convert source code into something that

the computer understands. Now, instead of learning the computer’s native tongue, we write software in a
language that makes sense to us, and we leave the task of conversion to the computer. The computer does
more work than it used to, and humans do less. This arrangement works nicely because computers are
very good at the type of work that is required to convert source code to machine languages, and, because
computers are faster than ever, there is plenty of extra processing power for these conversions.

Nevertheless, it is not as though we are free to explain to the computer what we want in plain English. We
still must learn a computer language such as C++. And, while easier to understand than machine
language, understanding C++ takes some practice. Modern computer languages are a compromise
between machine language and truly human languages.
C++ Language Features
So far we’ve learned that C++, like all other programming languages except machine language, derives its
power through abstraction, and at least part of its speed from the fact that it is a compiled language. Now
let’s talk about how C++ compares to other languages, and what makes it a natural choice for game
programming.

C++ is sometimes referred to as a mid-level language a reference to its level of abstraction. C++ is more
abstract and therefore higher level than assembly language, and yet less abstract and lower level than a
scripting language such as JavaScript. This mid-level status is part of the reason that C++ makes a good
game programming language. C++ is low-level enough to allow very detailed instruction, and yet high-
level enough to allow for very complex concepts to be expressed and organized. Both are important for
game programming, which must address the computer hardware at a very low-level, and yet express and
manage high-level concepts such as the imaginary universe in which each game takes place.

C++ gets much of its low-level ability from its predecessor C, which allows data to be manipulated with
almost as much control as that provided by assembly language. Combined with higher-level data handling
functionality, this means that data can be manipulated either in large, complex data structures, or down to
the most fundamental level: the bit. Likewise, both C and C++ are procedural languages, meaning that
they both require that code be grouped into functions a function being a set of one or more instructions
that the computer is to execute. By providing support for the definition of functions and a variety of data

types, C and C++ provide the basic building blocks upon which any program can be written.

In this respect languages such as C and C++ are not unlike machine language except that names can be
given to both functions and data. But what if, instead of using a name to represent data, we wanted to use
a memory address to indicate where the data resides, as machine language does? This would allow us to
control not only the value of the data, but it’s location in memory as well. C and C++ support this ability
with pointers. A pointer is special data type that contains a memory address. It points to data by
indicating its address.

Pointers have a bad reputation. They are often mentioned as the primary reason why C and C++ are
difficult languages to learn. But pointers are very popular with those who have grasped the concept. The
truth is that pointers can be overused. Using pointers just for the heck of it tends to obfuscate code, and is
a common practice for insecure programmers. There are situations, however, where pointers are
invaluable. We’ll use pointers whenever it is appropriate throughout this course, starting in Lesson 2.

While C++ provides the features provided by C (functions and data types), the same is not true in reverse.
The C language is—for the most part—a subset of C++. C++ extends C by adding high-level features that
make it much more powerful than C. The primarily addition takes the form of classes. which are

www.gameinstitute.com Introduction to C and C++ : Week 1: Page 7 of 42
essentially the marriage of functions and data. (The name originally considered for C++ was C with
classes.) In C++, an object is a single instance of a class.

In C and C++, functions use data, and data can be manipulated by functions, but classes allow functions
and data to be defined as part of a single object. This is a simple concept that has powerful connotations,
because it allows programs to be modeled more closely on reality. By creating objects that contain both a
state (the data), and a means for modifying that state (the functions), C++ allows real world entities to be
modeled much more accurately and naturally. The object-oriented features of C++ make it an ideal
language for designing complex systems.


Combining functions and data to form objects is a powerful addition on its own, but is multiplied by the
fact that objects can be extended to create new, more powerful objects, without modifying the original
objects. This is called inheritance or polymorphism. Inheritance allows a new class of objects to be
created by defining only the ways in which the new type of object differs from the original type of object.

This course introduces C++ starting with the low-level features, and moving to the high-level features. In
this lesson and continuing in lesson 2 we’ll cover the fundamental features that C++ inherits from C. In
lesson 3 we’ll delve into C++ specific support for objects. In the remainder of the course we’ll build on
this foundation by exploring game-specific uses for these language features.

Before we get to the C++ language itself, we need to talk about the tools and processes that must be used
in order to convert C++ source code into an executable form. Programming, like any other craft, such as
carpentry, painting, or mechanics, requires that you become familiar with the tools of the trade before you
can fully concentrate on the craft itself. Knowing the C++ language is useless if you can’t usher your
source code into a usable form, just as knowing how to paint is useless if you don’t know how to acquire
and mix the required pigments.

Once we have an understanding of the tools with which we’ll be working, we will introduce the
fundamental C++ language topics upon which the remainder of the course—and the rest of your C++
programming career relies.
Development tools
Programmers generally come out of two camps: Windows and Unix. Programmers familiar with
Windows programming often start with Visual Basic, which provides an Integrated Development
Environment (IDE). An IDE is an application that allows the programmer to create and manage projects,
edit code, and compile source code into a form that is machine-readable. IDEs typically provide
debugging support as well, which allows the workings of a program to be scrutinized by stepping through
the code, line by line, as it is executed. IDEs often provide “Code Wizards” capable of generating small
projects or injecting code into existing projects in order to add new features. When you use an IDE, you
usually don’t see the contents of all of the code or the project files that make up each project. This has the
advantage of allowing you to concentrate on the application specific portions of the code and ignore a

significant portion of boilerplate code and configuration data.

Unix programmers, on the other hand, usually learn to program using command-line tools. In this case,
each of the tools required for programming is executed separately. There is no common graphical user
interface that unifies the programming tools. Code is compiled with one tool, linked with another tool,
and debugged with yet another tool (we’ll talk about each of these steps in more detail shortly.) In a
command-line environment, the management of code modules and projects is done by hand. Command-
line programming requires a higher level of familiarity with each project component than is required
when programming with an IDE.

www.gameinstitute.com Introduction to C and C++ : Week 1: Page 8 of 42

Windows C++ programming offers both options. Visual C++, for example, provides an IDE from which
C++ applications can be developed and tested. For Visual Basic programmers, switching over to the
Visual C++ IDE is fairly painless, as the interface and concepts are similar. But C++ has long-standing
ties with Unix, and as such still provides command-line tools. The Visual C++ IDE, in fact, merely
invokes these command-line tools behind the scenes. This means that programmers can opt to use these
command-line tools directly, and forfeit the use of the IDE. But if you’re new to programming, your best
bet is to start with an IDE.

Despite the fact that Visual C++ currently dominates the C++ market, it is important not to forget that it is
not the only option. Borland, for example (a company that dominated the C++ development tool market
for years before Microsoft, and is in large part responsible for the popularity of C++ on the PC platform)
offers a C++ development system called C++ Builder. Although it is not nearly as popular as Visual C++,
it is a perfectly good C++ development tool. These are just two of the development tools available for
Windows, and other platforms, such as Macintosh and Unix have C++ development tools of their own.

Because the emphasis of this C++ course is game development, and because the vast majority of games
and game-related tools are Windows based, we’ll concentrate on the Windows platform. This won’t be
obvious at first, as the samples that we start with don’t use any Windows-specific features, but later, in

order to introduce graphics, we’ll be using Microsoft’s DirectX toolkit, which is Window’s specific.

The development tools that we’ll focus on are Microsoft Visual C++ and Borland C++, each for different
reasons. We’ll target Visual C++ because it is by far the most prevalent C++ tool, both for game
development and in general. And, whatever your personal feelings about Microsoft, Visual C++ is a very
good tool. We include Borland in the mix both so that we don’t forget that Visual C++ isn’t the only C++
development tool, and because it is free.

In an attempt to attract customers, Borland has made the command-line version of their C++ tools freely
available. There’s no IDE, but a fully functional version of a very up-to-date tool is yours at not cost.
(There are free development tools available for Unix, so Unix users will be less surprised at this, but
Windows users are less accustomed to free development tools.) So, if you lack the funds to buy Visual
C++, or are not inclined to do so for personal reasons, there is an option. Each of the samples in this
course, in addition to including Visual C++ project files, includes support for the Borland compiler as
well. The command-line Borland C++ tools are available at this URL:



There is one additional reason why Borland is supported in this course. The Borland tools are ANSI
compliant. ANSI (American National Standards Institute) is an organization through which proposed C++
language features are ratified and thereby ushered into the official version of the language. Visual C++
includes many features that are of Microsoft’s own design and are not ANSI compliant. By checking your
work even if just occasionally with the Borland compiler, you can be sure that you aren’t inadvertently
using Microsoft-specific C++ features. This is a non-issue if you’re positive that your code need only
support Windows, but if you think you might want to use your code on Linux, for example, it is important
to keep an ANSI compliant compiler around.
C++ Mechanics
The code required for any C++ program is stored in a standard text file, usually with a .cpp extension.
The filename main.cpp, for example, might be used to store the primary source code for a project.


www.gameinstitute.com Introduction to C and C++ : Week 1: Page 9 of 42
Because cpp files are text files, they can be edited with virtually any text editor, such as Windows
Notepad.

In practice it is best to use an editor that is intended for C++. The Visual C++ editor, for example,
highlights language keywords and comments using different colors, making the code easier to read (in
theory, at least). Starting with Visual C++ 6, the IDE editor also makes suggestions while you type. While
this feature is of questionable value in a word processor, it is genuinely useful for writing source code, as
it can reduce time spent looking up function names and arguments.

The cpp file is human readable, but meaningless to Windows or any other operating system until it is
compiled. Compiling cpp files is performed with a C++ compiler, but the compiler is actually just one of
the tools required to convert source code into an executable form. C++ requires three steps in order to
convert source code into an executable form:

• Preprocessing
• Compilation
• Linking

The first two steps, preprocessing and compiling, are typically performed by a single tool, and therefore
appear to be the same step. Nevertheless, preprocessing is a separate and distinct step. The preprocessor
responds to different C++ language constructs than the compiler, and the compiler does not recognize
these constructs, so compilation cannot occur until the source code has been preprocessed.
The preprocessor
Preprocessing serves several purposes, one of which is to strip any comments out of the code. Because
code comments are removed by the time the compiler is invoked, the compiler is free to treat everything
encountered as code. In addition to comment removal, the preprocessor performs these two tasks:

• Macro expansion
• Header file inclusion


C++ macros work on a simple search and replace basis. Macros are used to define text that, when found
by the preprocessor, is replaced with other text. This is a simple and powerful tool. Macros can be used to
substitute complex instructions or even sets of instructions with simple names. Macros can also be used to
give frequently used values or strings simple and logical names. This allows multiple uses of a value to be
changed just by changing the macro definition. Macros can even be used to redefine standard C++ data
types.

The simple search and replace nature of macros is also what makes them dangerous. Unlike the compiler,
the preprocessor has a very limited and simplistic understanding of C++. This makes it is easy to write
macros that use conflicting data types, or work in one case but fail in others. The preprocessor performs
no type or syntax checking on macros, so the task of reporting problems falls to the compiler. And, while
the compiler will detect and report these problems, it has trouble reporting these errors efficiently because
the compiler is using the expanded version of the macro. When macros are used, the code you see in your
editor is different from the code that the compiler is given. Any errors that the compiler reports are
therefore reported in terms of the expanded macro, and do not reflect the name of the macro.

There’s another reason to be wary of macros. Consider, for example, that your program requires a lengthy
and frequently used operation. Rather than write code for the entire operation each time it is needed, you
can write a macro to perform the operation. This has the desired effect of centralizing the code required

www.gameinstitute.com Introduction to C and C++ : Week 1: Page 10 of 42
for the operation and simplifying the remaining code, but is has a possibly unwanted side effect. The
preprocessor, each time the macro is used, expands the macro. If the macro is used more than once,
multiple segments of identical code is expanded into your source code. To the compiler, it’s as though
you typed in the entire contents of the macro for each usage. This can be a waste of memory, and can
even have detrimental effects on performance.

With C (as opposed to C++) there are several cases where using macros is required, but C++ provides
safer alternatives for most of these cases. It is therefore usually best to avoid macros. Macros do have

their place, but it is a good idea to consider other options before using them.

Header file expansion is another task that is performed by the preprocessor. Header files, which typically
have a .h extension, are used to define data structures, macros, and special functions that are common to
multiple cpp files. Header files are never provided directly to the compiler. Instead they are inserted into
cpp files, which in turn are passed to the compiler. The preprocessor, whenever it encounters a header file
insertion command in a cpp file, inserts the contents of the header file into the cpp file. This is, in fact,
another form of a macro substitution, except that in this case the contents of an entire file are being
inserted into the code. The preprocessor doesn’t read header files except to remove comments and expand
macros. In all other respects the header file is simply pasted into the cpp file.

This means that the contents of a header file, once it has been inserted into a cpp file, are treated exactly
like the content of a cpp file. The compiler doesn’t know or care that the code it is compiling came
from a header file or a cpp file. Anything that can be put in a cpp file can be put into an h file, and vise
versa. Despite this fact, there are rules that should be followed about what gets added to header files.
We’ll talk about this distinction in Lesson 4.
The Compiler
The heart of any C++ development system is the compiler. This is the tool that reads C++ source code, in
the form of cpp files, interprets the data structures and code, and converts then into a binary form more
suitable for executables. The compiler does not, however, generate the executable output required to run
the resulting program. This is the task of the linker, which we’ll talk about soon.

Unlike the preprocessor, which understands just a few items in a cpp file, the compiler must understand
every character in the source code. If the compiler encounters anything that it does not immediately
understand, it generates at least one error message, and no output file will be generated.

To say that the compiler protests each time it encounters anything that it does not immediately understand
is not an exaggeration. In C++, with the exception of the standard data types, every construct that your
code uses must first be declared or defined. If a variable appears in the code that has not been formally
introduced, compilation will fail. If a function is called before being either defined or declared in advance,

compilation fails. (We will talk about the difference between definition and declaration soon.) Unlike
Visual Basic, which by default allows variables to be used without having been given a type in advance,
C++ is extremely type sensitive. No ambiguity about the nature of a variable or function is allowed.

If the compiler is able to interpret the contents of a cpp file without any errors, an output file is produced.
The output takes the form of an obj, or object file. (The term object, in this case, doesn’t have the same
meaning as that used in object oriented programming.) The obj file contains the compiled code in a form
that is very close to that of an executable, but lacks fundamental mechanisms and formatting required for
execution.


www.gameinstitute.com Introduction to C and C++ : Week 1: Page 11 of 42
Also, the obj file often represents only a portion of the code required for a complete application. Each
cpp file that is passed to the compiler results in one obj file. But a robust C++ program might have
dozens, or even hundreds of cpp files. The resulting obj files must be combined and reformatted in order
for an executable to be produced.
The Linker
Using the output from the C++ compiler, the linker performs the final tasks required to assemble an
executable. The linker, given one or more obj files, attempts to generate a single executable. If any
problems are encountered, the linker generates error messages. These messages are similar to the error
messages produced by the compiler, but linker errors tend to be less common than compiler errors. There
are also fewer possible linker errors.

Unlike the compiler, which generates just one primary type of output file (the obj file), the linker can
produce executables (or .exe files), library files (.lib files), or Dynamic Link Library files (.dll files).
Unlike exe files, which can be executed directly, lib files are used to store collections, or libraries of
compiled code. Typically lib files are used to store frequently-used functionality that can be used in more
than one final executable. For example, if you were running a game development studio, you might use
library files to store code that is shared between game projects. In this case the lib file would be necessary
for the compilation of each game. Once each game is compiled, the code contained within the lib files is

included in the executable, so the lib file is not required at runtime.

Dynamic Link Libraries are similar to lib files in that they contain compiled code, but are closer in
relation to executables because they are used at run-time. In the game studio scenario, common code
might alternatively be stored in a dll file, but the dll would not be required for compilation. Instead, each
game would require the presence of the dll only during execution. Only a header file and a type library
describing the dll features are required for compilation.

For our purposes, we’ll focus primarily on generating executable files. Especially in these early lessons,
our programs are too small to warrant the use of lib or dll files. Later, however, when we introduce
graphics and user input code into our programs, we’ll use compiled code libraries.
Compilation Process
To summarize the C++ compilation process, our primary concern is source code contained in cpp and h
files. To convert this raw source code into an executable form, a compiler, using either an external or
internal preprocessor, removes comments, expands macros, and inserts any header files that are used by
each cpp file. The result is one obj file per cpp file. The final step involves the linker, which converts obj
files into an exe, dll, or lib file. This process is illustrated below.


www.gameinstitute.com Introduction to C and C++ : Week 1: Page 12 of 42


Knowing what is involved in assembling C++ programs is important, but, regardless of whether you’re
using an IDE or a command-line tool, it’s not necessary to perform each step separately. The IDE, or a
command-line make utility will decide if and when each step is necessary, and perform it when necessary.

This brings up an important point. Most of the time it is not necessary or desirable to perform the entire
compilation process. If a game has dozens of cpp files, for example, and you make a change to one of
them, it’s only necessary to compile the modified module. The linker can then use the newly compiled
obj file module along with the existing obj files to generate a new executable. This saves the time of

compiling the vast majority of code. For the small programs that we’ll start with, this is a non-issue, but
as a project grows, it becomes more important. It is not uncommon for a full-scale game to take 30
minutes or even an hour for a full compile, even on a fast machine.

The C++ compilation process illustrates that many of the file types involved are disposable. Since
intermediate files, such as obj files, and final files such as exe and dll files are either the direct or indirect
result of the source code files, they can always be recreated. Therefore, for making backups of your
source code, or emailing a project to a friend or teammate, there’s little point in including these files. This
is good to know, since obj files, and some other compiler specific files, such as the Visual C++ pch file
(precompiled header file) tend to be quite large.
Project files
Writing C++ programs primarily involves writing and editing source code files (cpp and h files). But
other types of files are necessary in order to keep track of which source code files belong in a project, and
what dependencies exist between these files. These files are called project files.


www.gameinstitute.com Introduction to C and C++ : Week 1: Page 13 of 42
Visual C++ 5 and 6 use the dsp and dsw extensions to denote project files. (Visual Studio 7, otherwise
known as “Visual Studio.NET” no longer uses the dsp and dsw file extension for project files.)
Command-line compilers use makefiles, which sometimes have a mak extension, but are often named
simply “makefile”.

Although these files are not considered to be source code, they have much in common with the cpp and h
files that contain the source code. They are text files, they are necessary (or at least very useful) in order
for compilation, and recovering them if they are lost or deleted is time consuming. As a result, these
project files should be treated just like source code files. They should be included in backups, modified
with care, and should be deleted only if you’re positive that they are no longer needed.

This brings us to the subject of the samples and exercises that we’ll study in this course. For each sample,
you’ll be given source code in the form of cpp and h files, and project files, both in the Visual C++ format

and in the Borland command-line makefile format. If you are using Visual C++, loading the project is just
a matter of double clicking the dsw file.

Borland users will be working from the command prompt. Compiling the provided projects means
changing into the directory where you’ve saved the sample files, and launching the make.exe utility
provided with the compiler, which will in turn launch the required tools—in the correct order to compile,
and link the project.
Release and Debug Builds
By default most C++ projects are configured to produce two different versions of the executable: release
and debug. On the surface both look the same, but ultimately, the release build is the version that will
serve as a final executable version. The release build is smaller in size, and provides faster performance
because, in preparing this version, the compiler and linker were instructed to include only the essential
information, and to optimize for speed.

The debug build is a larger and slower version because no optimization is performed, and the debug build
includes information that is not required for normal execution. For example, the names of your functions
and data elements are all embedded into a debug build. These names, although vital for reading source
code, are normally disposed of by the compiler. (Remember, the compiler converts C++ source code to
machine language, and machine language doesn’t use text-based names). Despite their speed
disadvantage, debug builds are useful during development because they can be used with debugging tools.

Debugging tools, or debuggers, allow executables to be run interactively in a way that allows you to see
the effect that each line of code is having, allowing problems (bugs) to be located. The debugger displays
your code, and allows you execute it one line at a time, or up to any other line, and allows you to inspect
the current value of each data element along the way. In order to display source code and run executable
code in a synchronized fashion, the debugger requires a debug build.

The Visual C++ IDE provides an integrated debugger, and Borland provides a free version of their
debugger, so you can test debug builds regardless of which compiler you’re using. The samples provided
with this course include projects files that generate both debug and release builds.

Windows applications types
Before we get to our first program, we need to talk about the types of programs that we will be writing—
at least at first. The typical windows program, the ones we’re most used to seeing and using in Windows,
are windowed applications. C++ can be used to create windowed applications, but these programs are

www.gameinstitute.com Introduction to C and C++ : Week 1: Page 14 of 42
considerably more complex than the alternative. For this reason we’ll postpone learning about windowed
applications for now.

The alternative is called a console application. Console applications are text-based programs, and are
typically used for fairly utilitarian purposes. Console applications don’t support any of the user interface
components used in windowed applications such as buttons, checkboxes, or even popup menus. Despite
their Spartan appearance, console applications offer a key advantage over windowed applications:
simplicity. A small console application can be written in as little as 5 lines of code, whereas a simple
windowed application requires closer to 50 lines. Except for the lack of graphical support, console
applications enjoy every benefit of Windows programming.
Hello World
There is a programming tradition that the first program that a student is given is the “Hello World”
program. In observing this tradition, let’s start with a simple program that, when executed, displays the
text “Hello World!” within a console window. Here’s what the HelloWorld program looks like when
executed:



Admittedly, this is a humble start, but we’ll be writing more complex programs soon enough. The
HelloWorld program is implemented with a single cpp file, called HelloWorld.cpp. The contents of this
file appears here:

// The HelloWorld sample
#include <ostream.h>


int main()
{
cout << "Hello World!" << endl;
return 0;
}

The HelloWorld sample starts with a comment. Comments are ignored by the compiler, so they have no
effect on the final program. They are supported by the language so that programmers can leave notes in
the code.

The next line has an include directive. This is a preprocessor command that indicates to the preprocessor
that we intend to use at least one function or data type provided in a header file—in this case the
ostream.h file. The ostream.h header file is a standard header file, meaning that it is included with the
compiler. As such we don’t need to provide this file, nor concern ourselves with its content. We include
this file so that we can use the cout object, which we’ll talk about soon. Preprocessor directives are

www.gameinstitute.com Introduction to C and C++ : Week 1: Page 15 of 42
prefixed with the pound sign (#), so header file inclusions like the one above, and macro definitions
(which we’ve yet to see) both begin with the pound sign.

HelloWorld is implemented in a single function called main. This function is not arbitrarily named. The
main function serves as the starting, or entry point for all console applications. It is the first function
called, and the last to exit. All of the processing that console applications perform takes place either in the
main function, or in a function that the main function calls.

The function name, main in this case, is preceded by a return data type, and followed by a parameter list.
We’ll talk about return types and parameter lists later in this lesson. For now it is enough to know that the
int that precedes the function name indicates that the function is expected to return an integer, or whole
number, and that the empty open and close parentheses indicate that this function takes no parameters.


C++ uses curly braces ({ }) for several purposes, including defining function bodies. The function body
for the main function starts with an opening curly bracket, and ends with a closing bracket. The body
contains two commands. The first, using the standard C++ output object (cout) outputs two items. One is
a string (a collection of characters), and the other, endl, is a symbol that indicates end-of-line. Both of
these items are provided to cout using the << operator. This line performs the output of a string to the
console window.

C and C++ provide operators to allow the manipulation of data. The multiplication operator, for example,
is represented by the asterisk (*), and the addition operator is the plus sign (+). C++ allows programmers
to redefine the meaning of these operators, and even assign meaning to operators that are otherwise not
supported. The cout object uses this technique to employ the insertion operator (<<). As a result, data can
be inserted into the output stream that the cout object represents.

Using techniques that we’ll discuss in Lesson 3, the cout object defines special meaning to the <<
operator. In the HelloWorld sample, this operator is used to send a text string to the output window, but
the cout object is not limited to displaying text. Numeric values can also be displayed, simply by sending
them to cout will the << operator. We’ll use this ability later when we learn about the C++ data types.

Finally, the main function uses the return command to indicate a return value and terminate the function.
The HelloWorld function always returns zero, which, in the case of the main function, typically indicates
that no errors occurred. The main function return value is typically ignored, so in this case the return
value is not important.
Keywords
Although there aren’t many, some words are part of the C++ language. These words are called keywords,
and cannot be used as function or variable names. So far we’ve used just one C++ keyword: return.
These are the keywords that we’ll use in this lesson:

• return
• int

• float
• double
• long
• short
• signed
• unsigned
• for

www.gameinstitute.com Introduction to C and C++ : Week 1: Page 16 of 42
• while
• do

The word main is a special function name, but is not a C++ keyword. Likewise, cout is part of the
standard C++ library, but not part of the language. Throughout this course, when introducing new
symbols, we’ll take care to indicate whether they are C++ keywords, symbols provided by the standard
library, or items created specifically for this course. Also, we’ll occasionally use a function name in a
code snippet that doesn’t actually exist at all, but is just used as an example.
Code Formatting
Each of the instructions in the main function body is terminated with a semicolon. C++ uses semicolons
to terminate commands and data types definitions. Forgetting any of these semicolons will result in a
compiler error. Omitted semicolons are probably the most common beginner mistake. (Semicolons are
used so often in C++ that before long you’re likely to start putting semicolons after constructs that don’t
require them.)

The fact that semicolons are required to terminate statements may seem counterintuitive because—to a
human—it is obvious where each statement ends. After all, each instruction appears on a separate line.
But C++ is a free-form language. We’ve included each instruction on a separate line purely for
readability. The compiler ignores virtually all spaces, tabs and carriage returns, so semicolons are
required in order to discern one statement from the next. Because the compiler ignores spacing and
formatting, we could have written the main function on one line, like this:


int main(){cout<<"Hello World!"<<endl;return 0;}

This code will compile, and will result in exactly the same executable as the previous version, but is hard
for humans to read. (Even if you happen to prefer this formatting, you would become extremely
unpopular with anyone that had to read your code.) Notice that in the example above the space that
appears between the words Hello and World. Unlike the other spaces, this one is significant because it
appears in a string. Omitting this space would change the output of the sample.

Although it isn’t strictly required, the C++ community, borrowing heavily from standards developed by
the C community, has adopted formatting guidelines that are largely agreed upon. For example, each
statement typically appears on a separate line, and each line is indented according to scope. We’ll talk
about scope in the next lesson. For now, it is enough to know that the statements within the main function
are indented by one tab because they are within a function.

There are, however C++ code formatting guidelines are not universally agreed upon. The majority of
Windows C++ programmers for example, always “line up their curlies”. Each closing curly bracket is
indented the same as its matching opening bracket, regardless of what is between them. The alternative is
to leave the opening curly bracket trailing on the previous line, like this:

int main() {
cout << "Hello World!" << endl;
return 0;
}

Ultimately, source code formatting is a matter of personal preference. But, before you decide to adopt an
unusual or unpopular style, keep in mind that someone other than yourself is likely to read or modify your
code. If your style is radical, they’ll have more trouble understanding your code. As a result, most

www.gameinstitute.com Introduction to C and C++ : Week 1: Page 17 of 42

professional programming teams agree, either by will or by dictate, on a general set of style guidelines.
Habits adopted now may have to be un-learned later if you find yourself working on a team.
Naming Conventions
C++ programmers also agree on a few naming conventions for function names, variable names, macro
names, and so forth. For example, function names typically begin with a capitalized letter, while variable
names typically begin with a lowercase letter. Macro names often are names with all upper-case letters.

That, however, is about the extent to which the majority of programmers agree. The remainder of
conventions depend on the platform (Unix, Windows, Macintosh), and the personal taste of the individual
or individuals involved. There are a few conventions that are common in Windows programming that you
will inevitably encounter, even if they aren’t used in this course.

Although we haven’t talked about classes yet (we will in Lesson 3), many programmers (including those
that write code for Microsoft), prefix class names with a capital ‘C’. CObject, CWinApp, CBitmap, for
example, are the names of classes in Microsoft’s MFC library (Microsoft Foundation Classes).

The majority of Windows programmers also use a naming convention known as Hungarian notation.
This convention is specific to the naming of variables, and dictates that the variable name be prefixed
with one or more letters that identify the type of the variable. This results in variable names such as
pszRegistryName and lpArg.

Partially because these conventions obscure the readability of code (especially when you’re first
beginning to learn C++), and partially because I don’t happen to be a fan of these conventions, we’ll
forgo some of these naming conventions in this course. We will follow the basic rules, which are virtually
universal, but not the more Microsoft specific conventions such as Hungarian notation.
Compile and Run
Before we continue, it’s important that you actually compile and run the HelloWorld sample, both to
familiarize yourself with the development tools, and to insure that the tool is installed and working
correctly. If you’re using Visual C++, you can load the project either by double clicking on the
HelloWorld.dsw file, or, from within the Visual C++ IDE, using the File|Load Workspace menu option to

display the workspace selection dialog and navigating to the HellowWorld.dsw file. Once the project is
loaded into Visual C++ it can be compiled by pressing F7 or using the Build|Build HelloWorld.exe menu
option.

If you’re using Borland C++, you’ll need to launch a command prompt window from the Windows
Start|Programs|Accessories menu, and navigate, with the cd (Change Directory) command to the directory
where you unpacked the sample files. Then run the make.exe utility. (See the message board for
instructions on how to configure Borland C++.)

Regardless of whether you’re using Visual C++ or the Borland tools, the sample should compile and link
without errors. If not, and you’re unable to figure out the reason, post a message on the message board
and I’ll help you find the problem.

Once the sample has been compiled, you’ll find that the development tool has generated Release and
Debug versions of an executable file called HelloWorld.exe. Visual C++ will place these executables in
sub-directories named Release and Debug. The Borland tools will use the directory names bccRelease and
bccDebug.


www.gameinstitute.com Introduction to C and C++ : Week 1: Page 18 of 42
To run the new executable, command line users can simply enter bccDebug\HelloWorld and press return
(to run the debug version). Visual C++ can launch newly generated executables from the IDE using F5
(the Debug version of the project is enabled by default). Given the way our sample works however, there
is one problem with this approach.

Programs that are run via the Visual C++ IDE are launched in a separate window, and this window closes
as soon as execution is complete. For the HelloWorld sample, this means that a console window will be
displayed briefly, and then will disappear before you have a chance to read the output. One remedy for
this situation provides us an opportunity to add some functionality to the same. We need to add code to
cause the HelloWorld to pause before exiting.


This can be accomplished with the getch function, which halts the execution of a program until a key is
pressed. First, we’ll need to include the header file that defines the getch function, and then we’ll need to
call getch after the sample output has been displayed, but before the main function returns. We should
also add a message explaining that the user should press a key. With these additions the HelloWorld
sample looks like this:

// HelloWorld with a “press any key” message
#include <ostream.h>
#include <conio.h>

int main()
{
cout << "Hello World!" << endl;

cout << endl << "Press any key" << endl;
getch();

return 0;
}

This version includes two header files, one for cout (ostream.h) and one for getch (conio.h), and uses the
cout object twice. Notice that and extra endl is used in the second usage to produce a blank line between
the two output lines. Now the sample can be run from Visual C++, and the console window will remain
visible until a key is pressed.
Comments
Although meaningless to the compiler, comments can be a very important part of any project, especially
for ongoing projects or projects with multiple programmers. Even for code that you’re sure no one else
will ever see, it is often useful to leave comments for yourself, either because a section of code is
confusing, or because—over time—you’re likely to get foggy about exactly how the code works.


In academic settings students are sometimes encouraged to comment every function. I had instructors that
insisted that each function, no matter how small, be documented with a paragraph describing its purpose,
the input parameters, the output parameters, and any assumptions that the function makes. Taken literally,
this practice can be not only unnecessary, but wasteful. Most small functions and larger functions that are
appropriately named just don’t require documentation. Their purpose is evident. Time spent writing
comments—especially detailed comments—can be time taken away from writing good code.

Alternatively, commenting complex functions, or sections of code that merit special comment is always a
good idea. Comments should also be used to point out what might not be obvious about the code. If the
name of a function needs explanation, then perhaps the function should be renamed. If it’s unclear which

www.gameinstitute.com Introduction to C and C++ : Week 1: Page 19 of 42
parameters are for input and which for output, perhaps the names are misleading. Comments should not
be used as an alternative to writing well-structured, clear, and concise code. A good example of a useful
comment is one that briefly summarizes the workings of a long, complex function.

C++ supports two different comment formats. The first is a carry-over from C, and uses the sequence ‘/*’
to start a comment block and ‘*/’ to terminate the comment. This type of comment is typically used for
comment blocks that span multiple lines, like this:

/*
The CheckCollisions() function scans the player and
projectile lists looking for collisions. If a hit is detected,
the damage to the player is calculated and added to
his damage rating and the projectile is destroyed. This
function never removes players from the player list.
*/

This comment, in addition to being an example of a multiple-line comment, is an example of an

informative comment because it is brief yet coherent, and it explains things that would take longer to
learn by reading the code. Any text that appears between the comment indicators is either ignored by the
compiler, or removed by the preprocessor before the code is given to the compiler.

The second comment style is specific to C++ and applies to single lines. This comment uses a double
slash notation (‘//’). Here are two examples:

// BUGFIX: 4/5/99 – fixed bogus scoring in network version

flush(); // flush the output because the next operation is lengthy

Any text that appears after the double slash, up to the end of the line, is treated as a comment and ignored
by the compiler. Single line comments can start at any point on a line, so they can follow code, as in the
second example.

There are some compiler-specific variations. Nested comments are sometimes supported, but usually
require enabling compiler settings. This is an example of a nested comment:

/*
(typically a large comment block spanning multiple pages)

/* todo: group chat support */

*/

Nested comments are typically accidental—the result of commenting out a large block of code that
contains one or more smaller comment blocks.

Generally speaking, most programmers do not use enough comments. The efforts of those that do use
comments regularly and wisely are always appreciated.

Data Types
Ultimately, programming involves just two ingredients: functions and data. So far we’ve written one
function, and we’ll certainly write more soon, but first let’s take a detailed look at the C++ data types.


www.gameinstitute.com Introduction to C and C++ : Week 1: Page 20 of 42
What is a data type? A data type is a language construct that is used to describe a single data element.
Data types are concepts, or descriptions—they don’t actually exist in a program. They do, however,
describe data that exists in those programs. C++ uses data types to define how much memory is required
to store a given data element, and which operations can legally be performed on the data.

If data types don’t actually exist in a program, what are they good for? Among other things, which we’ll
discuss later in this lesson, data types can be used to create variables. A variable is an instance of a data
type. A variable is tangible—it exists in the program. It occupies the amount of memory specified by its
data type, and is variable because it can be used to store any value that is legal for its data type.

Cars can be used as an analogy. The auto maker, before manufacturing or ordering a single part, creates a
blueprint, or specification for a car. At this point the car exists in theory only. The blueprint specifies the
engine size, and transmission ratios, and even how that car looks, and yet the blueprint has nothing in
common with the car. The blueprint cannot be fueled, cannot contain passengers, and cannot be driven.
The blueprint is not the car, but the blueprint can be used to manufacture not just one, but millions of cars.
Data types are like blueprints, and variables are like cars.

Creating a variable from a data type is a declaration. To declare a variable is to create a new variable
using a data type. Variable declaration has this basic syntax:

datatype variablename;

The data type appears first, and is followed by any number of spaces or tabs (a single space is typical).
The variable name follows, which is any name of your choosing, so long as it begins with a letter or an

underscore (use of leading underscores is legal but discouraged). Variable names cannot include symbols
such as the dollar or pound sign. The declaration much be terminated with a
semicolon. Declaring an integer, for example, might look like this:

int playerScore;

This declaration creates a new variable that has playerScore for a name, and int as a data type. The value
of playerScore is undefined. This means that it has a value, but the value is unknown because it hasn’t
been explicitly determined. This variable could be anything, and could also be different each time the
program is executed. Clearly, using this variable before a known value has been assigned to it would lead
to unpredictable results. Variables that are declared but not assigned to a known value are uninitialized
variables, and are a common source of bugs. A value can be assigned to playerScore with the assignment
operator, which is the standard equal sign (=), like this:

playerScore = 0;

Notice that even with a simple assignment, the terminating semicolon is required. Variables can also be
assigned an initial value as soon as they are declared:

int playerScore = 0;

This is a short hand syntax that is not allowed in most languages.

More than one variable can be declared in a single statement, as long as they are of the same type. Here
are some examples:

int a1, a2, a3, a4, a5; // all variables have undefined values

www.gameinstitute.com Introduction to C and C++ : Week 1: Page 21 of 42
int b1= 1, b2 = 2, b3; // only b3 has an undefined value

int c1 = 4, c2 = c1; // both c1 and c2 are equal to 4

Initializing each variable is entirely optional, even when multiple variables are being declared in a single
statement.

Now that we know what a data type is and how to use it to declare variables, let’s talk about the C++ data
types. So far we’ve seen the int data type used—as a return type for the main function. Another important
type is the void data type, which is used to indicate no type. A function that has void as a return type
returns no value at all.

The int and void types are just two of the data types that are built into C and C++. These data types are
called intrinsic types, and, with the exception of the void type, can be divided into these categories:

• Boolean
• Integer
• Floating point
• String

The Boolean data type, supported in C++ as bool, is used to indicate binary values. Technically this
means that a Boolean can be either one or zero, but conceptually Booleans are more usually thought of as
being either true or false. Although a Boolean can be expressed in memory as a single bit, C++ uses a
byte (8 bits) to represent Booleans.

Until fairly recently, the Boolean type wasn’t a native C++ type, but currently C++ provides Boolean
support with the bool type. In addition, two new symbols have been added to the language to support the
bool type: true and false, which can be used to assign and inspect the value of Booleans.

Whole numbers are supported by the C++ integer category, for which these keywords are provided.

• int

• short
• long
• signed
• unsigned

In a sense, only int is a data type. The rest, short, long, signed, and unsigned, can be used as data types
by themselves, or as data type qualifiers that modify the meaning of the int type. For example, these two
variables have the same type:

short s1;
short int s2;

In this case the use of short implies the int type, so the resulting variables have the same type. Likewise,
the signed type can be used by itself, or with int, like this:

signed s1;
signed int s2;


www.gameinstitute.com Introduction to C and C++ : Week 1: Page 22 of 42
These two variables have the same type as well, because the presence of signed implies the int type as
well. This example is somewhat silly, however, the int type is signed, so s1 and s2 above could be
declared this way:

int s1, s2;

As a result, the signed type is almost never used. The unsigned type, however, is often used to declared
unsigned integers, either with or without the int type:

unsigned u1;

unsigned int u2;

Both u1 and u2 have the same type. They are unable to store negative numbers. Because signed numbers
must use one bit for indicating the sign of the value, unsigned variables can store larger numbers.
Whereas variable of type int can store numbers ranging from –2,147,483,648 to 2,147,483,647, an
unsigned int ranges from 0 to 4,294,967,295.

The short and long types are both signed values by default. The short data type indicates a 16-bit value
(capable of values from –32768 to 32767), and the long type is a 32-bit type, and therefore has a value
range identical to the int type for 32-bit compilers.

C++ provides three intrinsic floating-point types: float, double, and long double. The float type is a 32-
bit value, and the double type is 64 bits in length. The long double is also 64 bits in length for 32-bit
compilers, and is therefore rarely encountered.

Unlike the integer types, whose range can be easily calculated according to their size, the nature of how
floating point data is represented makes such calculations non deterministic. This is because floating point
numbers must store both the whole and fractional portions of a number. Depending on the value being
stored, the floating-point type adjusts itself for maximum efficiency. A very large number, for example,
requires that memory be dedicated primarily to the storage of the whole portion of the number, leaving
the fractional portion with very little space. In this scenario the granularity for the fractional portion of the
number will be very coarse. Likewise, numbers with complex fractional components can be stored, but at
the expense of the whole portion. The result is that floating point values work best when used with
homogenous values.

Like integers, floating point variables can be declared and left in an uninitialized state, or initialized
during declaration, like this:

float f1;
float f2 = 0.0f;

double d1;
double d2 = 1234.456;

Finally, the fundamental string data type is the char type. This is an 8-bit data type that is typically used
to store ASCII values (we’ll talk about ASCII later in this lesson). The char type is capable of storing just
one character, but when used in an array—a linear collection of data—this type can be used to store text.
In fact, the “Hello World!” text used in the HelloWorld sample is stored as an array of the char type,
despite the fact that this type was not mentioned explicitly in the source code. By including a string literal
in the code, a sequence of characters enclosed in double quotation marks, the compiler knows to use an
array of the char type to store the text.


www.gameinstitute.com Introduction to C and C++ : Week 1: Page 23 of 42
To make explicit the fact that the char type is used to represent strings, we can rewrite the HelloWorld
sample to look like this:

// an explicit-type version of HelloWorld
#include <ostream.h>

int main()
{
char helloText[] = “Hello World!”;

cout << helloText << endl;

return 0;
}

In this version we declare a variable named helloText using the char type. Unlike the Boolean, integer,
and floating-point variables declared previously in this section, helloText is an array. The square brackets

that follow the variable name indicate that the new variable is a collection of data elements. In this case
the size of the collection is determined automatically by the compiler. This automatic determination is
possible only because we are initializing the helloText variable with a string. Otherwise the compiler
wouldn’t know how large the array should be.

The actual size of the helloText array is 13 bytes, so this code could also be written with an explicit array
size, like this:

#include <ostream.h>

int main()
{
char helloText[13] = “Hello World!”;

cout << helloText << endl;

return 0;
}

Why is the helloText array 13 bytes long if there are only 12 characters in the text string? An extra array
element is required because C++ uses null-terminated strings. This means that the text in a C++ string is
followed by a terminator that has a value of zero (C and C++ often use the term “NULL” as a synonym
for zero). In our example, the compiler is automatically adding a null terminator after the exclamation
point. The null-terminator indicates the end of a string.
The IntMult Sample
Now that we know about the intrinsic C++ data types, let’s write a sample that uses some of these types.
The IntMult sample uses the integer types, and demonstrates what happens when data types are used
with numbers that are too large:

// the IntMult sample

#include <ostream.h>

int main()
{
cout << "IntMult sample" << endl;

www.gameinstitute.com Introduction to C and C++ : Week 1: Page 24 of 42

short a1 = 123, a2 = 456;
short a3 = a1 * a2;
cout << endl << "using short data type:" << endl;
cout << a1 << " * " << a2 << " = " << a3 << " (incorrect!)" << endl;

int b1 = 123, b2 = 456;
int b3 = b1 * b2;
cout << endl << "using int data type:" << endl;
cout << b1 << " * " << b2 << " = " << b3 << endl;

int c1 = 123450, c2 = 67890;
int c3 = c1 * c2;
cout << endl << "using int data type:" << endl;
cout << c1 << " * " << c2 << " = " << c3 << " (incorrect!)" << endl;

unsigned d1 = 123450, d2 = 67890;
unsigned d3 = d1 * d2;
cout << endl << "using unsigned data type:" << endl;
cout << d1 << " * " << d2 << " = " << d3 << endl;

return 0;
}


The IntMult sample uses several different integer types to multiply two numbers together and uses cout
to display the results. The C++ multiplication operator is the asterisk (*). Notice that cout, used with the
<< operator is smart enough to figure out what types of data are being supplied. This allows us to display
various types of data without being concerned about any conversions that are necessary for proper
display. Here’s what the output looks like:



The sample starts by using the short integer type. Two variables are declared with initial values, and a
third is initialized with the result of multiplying the first two, then all three are displayed. The two shorts
are initialized with the numbers 123 and 456, and that part works fine. But the result of multiplying these
two values together is too large for the short type. This causes an overflow, a situation where a data type
is unable to accommodate a value.


www.gameinstitute.com Introduction to C and C++ : Week 1: Page 25 of 42
Data overflow is not something that the compiler will detect, nor will it cause a runtime error or crash.
The resulting data is simply lost. The portion of the value that can be stored is, and the rest is discarded.
Therefore, the answer derived from the first multiplication is incorrect. The situation is remedied in the
second because the int type is used instead of short. This provides ample space for storing the
multiplication result, and the correct answer is displayed.

Overflow crops up again in the third section, despite the fact that we’re using the int type, because two
larger values are being used which overflow even an integer. In the fourth section, we use the same values
and get the correct result by using the unsigned data type. This works, but only because we’re using
positive values.
Functions
The cornerstone of procedural programming languages such as Visual Basic, Pascal, and C is the
function. And, although C++ is described as an object-oriented language, it too is essentially procedural.

Before we get to the object-oriented portion of the language, we need a thorough grasp of its procedural
abilities. A function is one or more instructions that are executed as a unit. We’ve written two functions
thus far, one for the HelloWorld sample, and another for the IntMult sample, but now let’s take a closer
look at functions.

Aside from the function body, functions have three primary components: a name, a return type, and a
parameter list. The functions that we wrote earlier had the name “main”, a return type of int, and an
empty parameter list, indicating that the function accepts no parameters.

Functions can be introduced in a program in two ways: declaration and definition.
The HelloWorld sample defines the main function by defining the function components and the function
body together, but functions can also be declared without the body. This doesn’t mean that the function
has no body, or that the function doesn’t do anything. Declaring a function means that the function
components are specified, and that the body will be defined later.

Functions are declared by using a function prototype. The prototype of the main function used in this
lesson’s samples looks like this:

int main();

A function prototype looks exactly like the actual function definition, but does not include a function
body. Instead, a semicolon follows the closing parenthesis.
What good is a function that doesn’t have a body? Function prototypes are necessary for situations where
we want to announce that a function exists, but aren’t ready to provide the function body. We’ll illustrate
the use of a function prototype soon, but first let’s rework the HelloWorld sample to use more than just
one function.

We’ll start by moving the task of displaying output to another function. We’ll write a new function, which
we’ll call DisplayOutput, and define it like this:


void DisplayOutput()
{
cout << "Hello World!" << endl;
return;
}

×