Lesson 6 Libraries, why we have them, and how to make and use them. In order to simplify the creation of programs for its customers, software vendors make available one or more libraries of functions which have general application. When you write a program in 'C' much, if not most, of the "hard work" is done by explicitly called functions, which you call by simply writing their names in your program script. Unfortunately there is a little bit more to it than that. If the function returns a value which is other than of type int, you have to tell the compiler the type of the returned value. An example will, I hope make things clear. Lets's suppose that you have been given the task of, making things stupidly simplistic for a book example, sorting a list of names into alphabetical order. ( Yes, I do know this can, and should be done in just one line of shell script! However that's another story for another day. ) You look diligently through the Programmer Reference Manual, discover that the prose is almost opaque, and find a couple of interesting looking routines called strcmp, and qsort. You decide to use these library functions. Now for just a moment lets consider the ins and outs of what, in effect, you have just done. You have just asked a member of the team of programmers who created the library to join you, by proxy as it were, in creating your masterpiece. A useful concept, which has been in use almost since the start of electronic computing. To re-focus the mind on the task at hand; let's look in the Reference Manual at the page for qsort(3C) - The 3C in parenthesis is the cryptic code which is the unix apology for a reference to section 3C in the Manual! So find section 3C and look up qsort. Now have a look at the SYNOPSIS, and notice that there is no mention of a header file to #include, and also notice that qsort returns a void, not an int. This means that there is no header file /usr/include/qsort.h ( for my version of unix - system V Release 3.2.2 - anyway ) and you have to declare qsort yourself as an external function. Also turn to the page string(3C) in the fine manual. Notice that the SYNOPSIS here includes the line #include so you have to put it in your program text. Once more an example to make it all clear. /* ----------------------------------------- */ #ident "@(#) qsort-demo.c" #include #include #include extern void qsort (); extern int strcmp(); /* Some compilers need this defined, most don't. */ char names[22][25] = /* Here are some names to sort. */ { "John Nagle", "Colin Douthwaite", "Ian Lance Taylor", "Brian J. Murrell", "Pete", "Geoff Mccaughan", "David Liebert", "Operator", "Bill Baucum", "Victor Volkman", "Chay R Harley", "Dan Romanchik", "Larry Kollar", "Gaston Ormazabal", "Arijit Chandra", "Kenneth Mark Hopkinson", "Kerr Hatrick", "Tim Love", "Robert M. Juranitch", "Jeffrey Micke", "Duong Quoc", "Jagadesh Vasudevamurthy" }; #define NUMBER_OF_NAMES sizeof ( names ) / sizeof ( names[0] ) main() { int i; /* ** Print the unsorted names. */ printf ( "The Unsorted Names.\n" ); for ( i = 0; i < NUMBER_OF_NAMES; i++ ) printf ( "%s\n", names[i] ); /* ** Print a prompt, and wait. */ printf ( "Press RETURN to continue: " ); fflush ( stdout ); getchar(); /* ** Now apply qsort to the arrary of character strings. */ qsort (( char * ) names, NUMBER_OF_NAMES, sizeof ( *names ), strcmp ); assert ( names[0][0] < names[1][0] ); /* Quick check to see it's done it. */ /* ** Print the sorted names. */ printf ( "The Sorted Names.\n" ); for ( i = 0; i < NUMBER_OF_NAMES; i++ ) printf ( "%s\n", names[i] ); } /* ----------------------------------------- */ Note very well:- I wanted 22 short character strings for the data items for the demo to sort. So grep, uniq, cut, tail, and finally a tiny bit of vi fished eminently suitable strings out of "mail.received". If your name is not on the list, well I'm sorry, but the world is not a fair place! So that's how you use library routines. I chose qsort because it is simple to use, and shows off a feature of 'C' well, that's the ability to use a name of a function as a pointer and then execute that function from within the called function. It's strcmp in this case. A quick look at the compiler output is instructive. As is the nature of the animal, a tin-pot little program, which should have taken all of ten minutes to get going in fact took more like two hours. I put it down to the fact that the Fine Manual did not make it adequately obvious that the data array acted on by qsort was the data itself. From reading the Fine Manual I got the impression that the array acted on was an array of pointers. You live and learn. It would be a much faster qsort if, in fact, the sorting function sorted pointers to data instead of the data itself. You might like to make a function qsort_p which worked in in this way. The qsort algorithm is well documented elsewhere. There is just one more point to notice about using function libraries. The 'C' compilation system will load functions from the library /lib/libc.a as a default. All others have to be indicated to the linking loader by a switch on the shell interactive command line. $ cc -o prog prog.c -L /usr/local/lib -lgdbm -lmalloc You might use this command line to compile and link a program which uses both the GNU gdbm data-base manager library, which is installed in the directory /usr/local/lib, and the enhanced malloc library. Now, there hangs a tale! I remember having to compile a program suit off Usenet and it just would not work properly. No error messages, no warnings, no missing linking-loader symbols. It just "died" when I tried to run it. After many, many hours of total frustration, I thought that I would try linking in the enhanced malloc library. Presto! It worked. Note very well. A common misconception is the notion that having a #include line in the source text will automagically tell the linking loader to get the functions from the appropriate library. Remove this erroroneous notion from your mind. It won't. The -lwhatever flag on the shell command line which initiates execution of "cc" or "ld" is the only way to tell the loader where to look for the required library. -- +----------------------------------------------------------------------+ | NAME Christopher Sawtell | | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| | EMAIL chris@gerty.equinox.gen.nz | | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | +----------------------------------------------------------------------+