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. We will (literally) leave that as an exercise for the reader.

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 two additional options when compiling "-Wall" and "-Werror".

-Wall is an option (like -o filename) for g++ that it can read off the command-line. It says "If I do anything in this program that is at all 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 everything it can warn you about it will. (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 -Wall in that they both deal with warnings. -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++ -Wall -Werror myprog.cc -o myprog
You may 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 immersion.)

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.

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

Do some online research, and write up a two-paragraph summary of why you have to execute your programs as "./program" and why this is a security matter.