Lab 1 Preparation

To prepare for your first Exercise, recall your experience with the vi editor and bash shell scripting. You will want to use vi whenever possible, although there are other editors available in the lab, because it is the one editor you can be certain will exist in some version on any system you may encounter. The version we use is called vim; other versions include elvis, vile, and the original and very basic vi, but they all have the same general functionality.

See Lab Introduction for some vi and gcc information on the course web site at <http://elearning.algonquincollege.com/coursemat/allisor>. You will also want to read over some of man 3 printf (and not man 1 printf) about using %s and \n in print formats.

The purpose of this Lab is to help you to refresh your skills, and not to write enormously long and complicated shell scripts. Once you have quickly (take no more than 15 minutes!) written and tested simple scripts for the first 2 parts of this exercise, you are ready to move on to exploring C programming and the gcc compiler. You may of course enter man 1 gcc for instructions, but the short version is to use:

gcc -ansi -pedantic -Wall -Wextra -O2 -o run-name source.c

which compiles source.c into source.o, and then links this with library functions into the executable file run-name (no chmod is needed because the compiler sets the correct attributes for you). The .o file (the object code) is then deleted as it is no longer needed.

The .c suffix on your source file is essential. The compiler uses the suffix to determine the type of file and what to do with it. The .c suffix is for C source and .h is for #include files. You will also use .o for object files in this course, and may occasionally see suffixes like .a and .s. If you don't specify the -o name option, the executable file defaults to the name a.out for historical reasons.

The other arguments (-ansi -pedantic) request strict compliance with the C89/C90 standard we will be using, and -Wall -Wextra request the highest level of error reporting. Finally, -O2 (that's capital-OH, not zero) asks for an optimization level that can detect additional bugs during compile and link.

The main() function of any program is the initial entry point called by the shell when you ask for it to be executed with ./run-name, and the values of argc and argv are built from your command-line arguments. The function main() itself is defined as:

int main( int argc, char *argv[] )

That is, the count of the number of arguments is placed in argc and a list (or vector, a 1-dimensional array) of pointers to the argument strings is created for you as argv. The last entry in argv (always at argv[argc]) is the value NULL, the null pointer, frequently defined as (void *) 0. For example, for

./program aaa bbb ccc (4 arguments)

Index into argv

String

0

Pointer to ->

"./program"

1

Pointer to ->

"aaa"

2

Pointer to ->

"bbb"

3

Pointer to ->

"ccc"

argc

NULL


Each string is a normal C string with a '\0' terminating it. This is also known as the NUL character in ASCII, hence the term NUL-terminated - do not confuse NUL the 1-ell 8-bit character with NULL the 2-ell pointer. The string "123" has a length of 3 bytes but requires 4 bytes to store it (see also the library function strlen() in man 3 strlen and the pages around page 39 in K&R2). In memory, it's seen as the hexadecimal value 0x31323300. See section 1.9 on page 28 of K&R. for more details.

Note that main() is always type int because it must return a number to the shell (consider $? in bash). You will usually end your main() function with the

return 0;

statement as a result. The only other valid form of the main() function, apart from the one above, is

int main(void)

The main() function never requires a function prototype.

Now read over all the instructions for Lab 1 and follow them carefully. You can see a model C program to start from in Section 1.1 of K&R2 starting on page 5.