C++ Under Linux
Being a course in C++, it is probably about time that we tackled the
all-important issue: how do we compile C++ programs in Linux?
g++
The very popular (and free) compiler for UNIX systems is gcc.
When used to compile C++ programs, it is generally invoked as
g++. Throughout this course we will be using g++ for
compilation. In its simplest invocation, we only need to call it with
the name of the program we are trying to compile. In this example we
will compile "hello.cc". (Note that the standard filename extension
for C++ files is now ".cc" rather than ".cpp").
Here we will try to compile the following:
hello.cc - version 1:
#include <iostream.h>
void main()
{
cout << "Hello World!" << endl;
}
Now we save that file (in emacs), and try to compile in the terminal.
> g++ hello.cc
In file included from /usr/include/c++/3.2/backward/iostream.h:31,
from hello.cc:1:
/usr/include/c++/3.2/backward/backward_warning.h:32:2: warning:
#warning This file includes at least one deprecated or antiquated
header. Please consider using one of the 32 headers found in section
17.4.1.2 of the C++ standard. Examples include substituting the <x>
header for the <x.h> header for C++ includes, or <sstream> instead of
the deprecated header <strstream.h> . To disable this warning use
-Wno-deprecated.
hello.cc:6: `main' must return `int'
Sadly, our program failed to compile, and g++ produced a lot of (somewhat)
mysterious output when we tried to compile it. Let's look more
closely at what happened:
In file included from /usr/include/c++/3.2/backward/iostream.h:31,
from hello.cc:1:
/usr/include/c++/3.2/backward/backward_warning.h:32:2: warning:
#warning This file includes at least one deprecated or antiquated
header. Please consider using one of the 32 headers found in section
17.4.1.2 of the C++ standard. Examples include substituting the <x>
header for the <x.h> header for C++ includes, or <sstream> instead of
the deprecated header <strstream.h> . To disable this warning use
-Wno-deprecated.
Is really just one long warning (note at the end of the third line
there it says "warning"). What this really means, in
very complicated language, is that we should not have
had "iostream.h", but rather "iostream", the new
standard. (Those of you that took CS 10 last quarter
are probably aware of this.)
Now let's look at the second bit of output
hello.cc:6 `main' must return `int'
Unlike Microsoft's version of C++, g++ enforces the standard practice
of having the main function be of type "int." This is fairly easy to
fix. Now let's see where we are:
hello.cc - version 1:
#include <iostream>
int main()
{
cout << "Hello World!" << endl;
}
Gives us the following output:
> g++ hello.cc
hello.cc: In function `int main()':
hello.cc:7: `cout' undeclared (first use this function)
hello.cc:7: (Each undeclared identifier is reported only once for each function
it appears in.)
hello.cc:7: `endl' undeclared (first use this function)
What? "cout" undeclared? Did we lose the ability to print things to
the screen when we moved from Windows to Linux?
Of course not. g++ enforces the new C++ spec regarding
namespaces. The namespace issue is a bit compilcated for this course,
but as last quarter's CS10 students can attest, this problem can be
solved in one of two ways:
#include <iostream>
int main()
{
std::cout << "Hello World!" << std::endl;
}
or
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World!" << endl;
}
Stylistically, it is probably best to get into the habit of using the
first method.
Regardless of your choice on this issue, let us see if this fixes our
simple program:
> g++ hello.cc
>
Nothing happens. Believe it or not, this is a good thing. (A rule of
thumb under UNIX is that if no output was generated, everything worked
correctly.) However, we still have not run our program. When
compiling, g++ creates executable files named "a.out" by default. If
you don't like this default choice (and who does?), then you can add
the "-o" command line parameter to pick your own filename, like this
> g++ hello.cc -o hello
(Note also that unlike Windows, no ".exe" extension is needed.) Now
we have a file called "hello" in our current directory that when
executed will (presumably) print out our friendly greeting.
> ./hello
Hello World!
>
It worked! You may be asking "Why do we have the ./ before the
hello?" This is a good question, but requires a fairly lengthy
explaination. Check the mailing list archive for the answer,
it was answered during July 2003.
At this point you should be able to use g++ from the command line to
compile a C++ program. However, to help you through some of the
complicated concepts that will come up in this course, we are going to
enforce the use of four additional options when compiling "-W", "-pedantic",
"-Wall" and "-Werror".
-W is an option (also called a flag) for g++ that is given
to the program on the command-line. It says, "I'd like you to
warn me about all of the simple mistakes that people might make."
This lets g++ do some of the checking for you that would otherwise
cause you lots of time and trouble. (Remember, warnings that are
caught are often logic errors that you don't have to fight! This
is a very good thing.)
-pedantic means that g++ will turn off some of the features
in the g++ compiler that are not part of the C++ standard. For the
most part these are fairly esoteric, but there are a couple common
things that people in this course would do with g++ that are not
actually allowed by the standard, so we enforce this flag in an
effort to prevent you from learning non-standard (bad) habits.
-Wall says "If I do anything in this
program that is really odd, warn me." C++ has a long long list of
things that could possibly indicate a programming mistake, but by
default many of them are not checked when compiling. Adding -Wall
ensures that many of the more complex things it can warn you about
will be reported. (It is like
having a very picky set of eyes checking over your program for you.
This is a good thing.)
-Werror is related to the other flags in that they all deal with
warnings. Unlike the others, it doesn't enable additional warning
messages. Instead -Werror tells the compiler "If you ever feel like warning
me about anything, consider that an error and do not compile any
further." This way even if you wanted to ignore the warnings, you
would have to find a way to convince the compiler that you really know
what you are doing. We are enforcing the use of these to flags so
that your programs are more likely to work on complicated input, and
because there really is no reason to have any warnings in a well
written program. For your home programming projects, we will compile
your submissions with -Wall and -Werror, so you should get used to
using them now.
So the general command line you will be using this quarter when
compiling by hand is:
> g++ -W -Wall -Werror -pedantic myprog.cc -o myprog
You probably want to memorize this.
Makefiles
The perceptive among you may have noticed the phrase "compiling by
hand" and the implication that there are more automated ways of doing
things. Indeed there are. One of the most common methods is called
"make." A fairly in-depth description of "make" can be found
here.
(Note that in the tutorial they assume you use the "CC" compiler. If
you simply replace "CC" with "g++" everything should be the same.)
Read this tutorial, bookmark it for future reference, and try to
create Makefiles for your own programs as we go through the quarter.
(The home program projects will require it.)
Makefiles are generally of more use with larger (multi-file) C++
projects. However, the use of them is a very very good habit to get
into, so we are pushing them early and often. Further, for those of
you that really don't like using the terminal, the "Tools->Compile"
option under Emacs defaults to calling "make" in the current
directory. So with an appropriate default rule, Emacs can be an easy
development environment.
Man Pages
While we touched on it briefly in the previous lab, we would like to
focus some effort on learning to read man pages. There is a huge
amount of information available in the man pages on a standard Unix
system, but the ability to really understand that information is a
skill that takes a bit of practice. (This isn't to say that they are
poorly written, it is simply that there is a vast amount of technical
knowledge and jargon that
can only really be gained by total immersion. This link is to a somewhat
tongue-in-cheek collection of computer geek terminology. It is purely
for entertainment purposes only.)
Note also that the man pages contain information on C/C++ functions in
addition to regular Unix commands. Being able to reference even this
subset of information effectively will help you out in this
course.
Helpful Download
If you save this file as .emacs in your
home directory and restart emacs, then your C++ code will come up
color-coded.
The Assignment
7 points:
Write a program in C++ that reads its input a single-character at a
time and prints out the numeric value of that character. Repeat until
there is no more input to read (for a note on how to do this, check here). For a table of the correct values (so you can
check your work), try the man page for the word "ascii".
Sample execution:
> ./numchar
a
97
$
36
~
126
^D
>
Submit your program as numchar.cc.
.2 points
Write a Makefile for numchar.cc that creates an
executable called numchar. Submit your Makefile.
.2 points
Add a target "clean" to your Makefile that deletes
the emacs backup file numchar.cc~ and the executable
numchar. Submit your Makefile.
.2 points
Read the man page for "diff". Write a brief
description (2 paragraphs) of what you find there. Save this as
diff.txt and submit it.
.2 points
Read the man page for "time". Write a brief
description of what you find there. Save this as time.txt and submit
it.
.2 points
Enter the following:
> man 2 time
Continuing in time.txt, describe what you find here. Was this what
you were expecting before?
.2 points
Read the man page for "man". Figure out which
"section" the C/C++ reference is in. Note anything else of interest
you find there. Save this as man.txt and submit it.
.2 points
Write up a two-paragraph
summary of why it is safer to run your programs as "./program".