Friday, January 10, 2003

Introduction

This lecture provides a general overview of the three languages we will be studying this term. A very short example of each program language is provided and details regarding how to compile and execute the programs are provided.

Compiling and executing a C program (K&R - § 1.1)

Here is a simple C program that, when compiled and executed, displays the string Hello world! on the screen:


/* Source file hello1.c */

#include	<stdio.h>

int
main()
{
	printf("Hello world!\n");
	return 0;
}


The source consists of a header file stdio.h which is textually included by the C preprocessor prior to compilation. Header files contain declarations required by the program. In this case, because the main program uses the printf() function, we must include the standard input/output header which contains an appropriate declaration for this function.

Note that there are several differences between this program and the corresponding Java program:


/* Source file Hello.java */

public class Hello {
	public static void main(String [] args) {
		System.out.println("Hello World!");
	}
}


For example, the C main() program is not included inside a class. C has no concept of classes. The main() function as well as the printf() function are essentially at global (or top-level) scope in the C program. The Java main() function also has an argument, an array of Strings which represent the command line arguments passed to the program. C's main() function can also access its command line arguments but two arguments are required by the main() program. (More on this later.)

The return 0; at the end of the C program is the value returned by the main() program to the command shell. A return code of zero is typically used by C to represent successful completion of a program or a function. The return type of the main() function (and indeed all functions in C) is designated at the beginning of its definition: int main(). Java, on the other hand does not return a value for main().

Before downloading and compiling this program, it would probably be a good idea create a separate directory for your 3710 source code and do all your work in that directory. To copy this source code, right click on the source code and select the Save Link As... option in the menu and save the file to your 3710 directory.

You can then compile and execute the program. This source file can be compiled on a typical Unix machine from a command line prompt as follows:

Method #1: Use the gcc compiler to compile the source program as follows:

$ gcc hello1.c 

(Note: '$' is the generic command line prompt.)

This will create a file called a.out which can then be executed as follows:

$ ./a.out 
Hello World!

You can also specify various flags to gcc to tell the compiler to generate warnings when it sees something in your code that may cause problems. You can turn on these warnings by invoking gcc as follows:

$ gcc -Wall -ansi -pedantic hello1.c 

It is usually a good idea to use these compiler options, especially when learning C for the first time.

Method #2: The program make can also be used to compile a variety of programming languages. Typically a Makefile is required for complicated programming projects, but for simple, single file programs, you can simply type:

$ make hello1

This will automatically compile the hello1.c source file in the current directory and create an executable hello1 which can then be executed as follows:

$ ./hello1 
Hello World!

Note that unlike the Java compiler, which generates byte-code (which must be interpreted), the C compiler generates an executable which can be run natively on the hardware without the use of an interpreter. As a result of this C programs are typically much faster than Java programs on the same hardware.

The Preprocessor

As described above, the preprocessor is executed prior to the compiler. During the preprocessing, #include directives are followed and #define macros (which will be described later) will be substituted throughout the source file.

If you would like to see the output of the preprocessor, run the compiler with the -E option:

$ gcc -E hello1.c 

More than 800 lines of code is generated by this command with the main() program located at the bottom. This is the source that the compiler actually uses when compiling the hello1.c program.

If you'd like to scroll back and forth through the output, you can pipe the output to a pager program (e.g. less) as follows:

$ gcc -E hello1.c |less

In the above command, we pipe the output of the preprocessor to less which allows you you move through the standard output of the compiler's preprocessor output by using the space bar to move forward and pressing Ctrl-U to move up. You can go directly to the end of the output by pressing G. You can terminate the pager by pressing q.

Compiling and executing a C++ program (K&M - Chapter 0)

Apart from the minor syntactic differences, the C++ program is very similar to the C program.


/* Source file hello2.cpp */

#include	<iostream>

int
main()
{
	std::cout << "Hello world!" << std::endl;
	return 0;
}


We now include the iostream header instead of stdio.h (note the absence of the .h extension from iostream). Also, instead of printf(), we use the std::cout standard output object and the insertion operator (<<) to display information. The std::endl represents the end of line character and is analogous to the \n (newline) character in the C program. Incidentally, the std:: prefix indicates that cout and endl are defined in the context of the standard library's namespace.

Again, you can compile and execute this program in a manner similar to above.

Method #1: Use the g++ compiler to compile the source program as follows:

$ g++ hello2.cpp 

Again, this will create a file called a.out (which overwrites any existing a.out file). This executable can then be run:

$ ./a.out 
Hello World!

The compiler options described above for generating warnings are available to g++ as well. Using them when compiling your programs can be very helpful.

Method #2: Again, we can use the make program to build a executable from this source file:

$ make hello2

This will now use the C++ compiler to compile the hello1.cpp source file in the current directory and create an executable hello2 which can then be executed:

$ ./hello2 
Hello World!

Running a perl program (S&P - Chapter 1)

Unlike C and C++ programs, perl programs are not compiled to an binary prior to being executed. Instead, perl is a scripting language which is compiled to an internal form and then executed.


#!/usr/bin/perl -w
#
# Source file hello3.pl

use strict;

print "Hello world!\n";


To run this program, you must first download it and turn on the execute permissions of the downloaded file. If we look at the long listing of the script, you notice that the user's permissions on a newly created file are usually set to read/write with no execution permission as indicated by the second, third and fourth characters (rw-) of the output below:

$ ls -l hello3.pl 
-rw-r--r--    1 donald   cs-grad        83 Jan  5 23:50 hello3.pl

We can turn on the execute bit for the user (i.e. the owner of the file) by using the chmod command as follows:

$ chmod u+x hello3.pl 

Note that it is only necessary to change the permissions once -- it is not necessary to change it everytime we want to run the perl script. Running the ls command now shows that the script has the appropriate permissions:

$ ls -l hello3.pl 
-rwxr--r--    1 donald   cs-grad        83 Jan  5 23:50 hello3.pl

You can then compile/execute it be calling the script by name:

$ ./hello3.pl 
Hello world!

The first line in the perl script is special. Upon seeing the '#!' special characters at the beginning of the file, the program immediately following these two characters will be executed to run the script. The -w option turns on warnings which can provide very instructive output about potential problems in your code when it is compiled and run.

Note that perl, like Java, is compiled internally to byte-code. However, the byte-code is not actually written to a file as they are when you compile a Java program. Instead, perl executes the byte-code immediately after it compiles the script (provided of courses, there were no compilation errors in the script).

A perl script can also be compiled and executed by invoking the perl binary directly on the command line. For example,

$ perl -w hello3.pl 
Hello world!

In this case, it is not necessary to have the execute permission on the file set, nor is it necessary to have the first '#!...' line in the script.

Amongst other features, the use strict; tells the compiler to enforce declarations of variables before use -- this can be very helpful when trying to find bugs in your perl programs. The use of -w and use strict; is strongly encouraged for all perl programs that you write.

Note that the perl program presented above does not explicity return a value to the invoking shell. In this case, perl will return 0, by default.

Last modified: Mon Jan 13 12:50:13 2003