| Related sites for http://www.docdubya.com/belvedere/cpp/cfcpppg.html |
| They_Host Offers shared web hosting and domain registrations. | | Totalspace Offer shared plans and domain registration. | | Interkey_net Web hosting, domain name registration, FrontPage 2000 hosting, application hosting and NT Hosting. | | Internet_Planners Hosting services, reseller accounts, and merchant accounts. | | Center_For_Internet_Research Contract research on markets, demographics, social dynamics, education, and any other nexus between the human experience and the internet. | | The_GIF_Controversy A 2004 article on the GIF controversy seen from a software developer's perspective. Includes original interviews, a historical perspective, and a detailed bibliography. | | Eiscream_com Reseller of biometric software solutions. UK | | The_Bistro_Programming_Language Article reprint from Dr. Dobb's Journal, March 2004. First three paragraphs are visible without registering. [Developer::Pipelines] (March, 2004) | | RFC_1566_-_Mail_Monitoring_MIB Defines a portion of the Management Information Base (MIB) for use with network management protocols, and extends the basic Network Services Monitoring MIB to allow monitoring of Message Transfer Agen | | Omniplex_Home_page Omniplex offers: NFS Software - NFS Clients, NFS Servers and NFS Gateway for file sharing between windows and UNIX, LINUX, HP-UX and AIX systems. Terminal Emulation Software - a range of terminal em | | GNU_Arch_home_page Tom Lord's home page for articles and discussions around GNU Arch. Mostly focused on the tla2 series. | | RFC_2204 ODETTE File Transfer Protocol. D. Nash. September 1997. | | Alpha_Webs Web site design. | | Cyber_Connections_Ltd_ Afforable web site design and development. Based in Alberta, Canada. | | Innovative_Publications Offers design including Flash, e-commerce, custom CGI scripts, development, domain name registration, hosting, and search engine submision. | | Mercury_Web_Solutions Web design, database development, hosting, and search engine optimization. Located in Albany, New York, United States. | | Ohio_Web_Technologies Web and graphic design, computer repair, and audio and video production. Located in Stow, Ohio, USA. | | Interactive_Intelligence,_Inc_ Developers of a proxy server. Site contains downloads, documentation and a forum. | | JFig_Java_Configuration_Management_Tool A Configuration utility that provides simple, flexible and powerful functionality for managing one or more configurations in a java environment. It uses a combination of a hierarchy of configuration f | | Vemuri,_V__Rao University of California, Davis - Digital Media, Soft Computing, Neural Networks, Genetic Algorithms, Numerical Methods. |
|
C for C++ ProgrammersC For C++ Programmers Introduction C Control Structures Free Functions Parameters Return Values Function Miscellany Other Control Structures C Data Structures Scalars Arrays Strings Structures Typedefs Pointers Memory Allocation Miscellany C Input/Output Compiling C Source FilesIntroductionBefore there was C++ there was C. Developed at Bell Laboratories in the early 1970's, C was used for over95% of the code in the UNIX operating system kernel. By the end of the 70's, C compilers wereavailable for most mini and microcomputers. Superior to BASIC for applications requiring efficient code generation,C became the de facto standard for application software development on mini-computers and that new phenomenon,the PC. Meanwhile, Bjarne Stroustrup, a Bell Labs research computer scientist, released a prototype language called``C With Classes.'' Originally a preprocessor that generated C code, this effort eventually produced C++. Meanwhile, C itself continued to dominate application development for personal computer software and real-timecontrol. Both C and C++ are used today for application software, systems software, and embedded systems.C++ can be viewed as C with richer support for object oriented development. Conversely, C can be viewedas a primitive variant of C++. In any event, most legal C programs are also legal C++, and the C++ compileris able to translate them. The few exceptions use features considered obsolete in C; these will not be discussed.Learning C means stripping away some of the comfortable assumptions under which C++ programmers work: whileC is simpler than C++, C also makes it easier to defeat type checking, scramble memory, and use pointers in anundisciplined way. The remainder of this document assumes you know C++ moderately well, and discusses Cin this context.C Control StructuresFree FunctionsIn C++, one uses classes to structure the system into components. Most of the functions in C++ are members ofa class, and thus tightly related to the class's objects. However, C++ also supports free functions:functions that are not part of a class. The free function you are most familiar with is main,which gets things going by creating, initializing, and activating one or more objects. Other examples are numericalfunctions such as sin and log, which really don't belongto any class.In C, all functions are free functions. There is no way in C to bind a function to a data structureor object. Any such relationships depend on the discipline of the programming team. The data structures manipulatedby C functions must be either global variables or explicit parameters: there are no implicit arguments likethis in C++.ParametersC does not have references or reference parameters. All arguments to C's free functions are passed by value.To achieve the effect of call by reference, pointers are used. Consider the following examples: void swap(int& x, int& y) { int t ; t = x ; x = y ; y = t ;}. . .swap(a, b) ; void swap(int *x, int *y) { int t ; t = *x ; *x = *y ; *y = t ;}. . .swap(&a, &b) ; The code on the left is standard C++, using reference parameters to exchange two integers. The code onthe right is the equivalent C version. As C always passes by value, we have to pass pointersto the two integers being swapped, and use the indirection operator * to accessthe values. In the call on the right, we use the ``address of'' operator &to create the necessary pointers to a and b . In thiscase, the C++ code is much cleaner, as the pointers are manipulated by the compiler ``under the hood.''Return ValuesC functions are severely constrained as to the types of values they can return: Scalars Scalars are simple values like integers, floating point numbers, and characters (not strings!) . Structures Structures are like classes with all public data and no operations. Any piece of code can select and modify the elements of a structure. Pointers Pointers in C can address simple values, structures, or arrays.Function MiscellanyThere is no way in C to overload a function (i.e., to have two or functions with the same name butdifferent argument lists). In a similar vein, there are no template functions in C.Other Control StructuresThe sequencing, iteration, and decision control structures in C are the same as in C++. That is, the whileand for loops, as well as the if and switchstatements, are identical. However, the types of values and structures you can use in decisions and iterationsare much simpler than in C++.C Data StructuresC data structures are fewer and simpler than those of C++. Most significantly, there are no classes inC -- the closest we can come to a class is a struct , which is a collection of relateddata items. The following subsections describe the basic C types and data structures.ScalarsThe predefined scalar types are the same in C and C++, namely: Floating point Numbers with both an integer and fractional component, represented in decimal or scientific notation. The two subtypes are double (double precision) and float (single precision). For most computations, double precision is preferable. Example constants 4.0 3.14159 6.023e23 Integer Integral values. The default int is the ``natural'' size for the CPU -- in most cases 32 bits. There are two variants, short int (or short) and long int (or long ) which are typically 16 and 32 bits, respectively. One can also specify non-negative integers by prefixing a declaration with unsigned . Characters (type char ) are just very small (1 byte) integers. Though they usually hold a single character, there is nothing to prevent their use as small numbers (other than a desire for sanity). Example constants 1234 'x' Note that character constants like 'x' are really small integers whose value is the character's ASCII code. Some non-printing characters have special escape sequences: \n Newline \r Return \t Tab \ooo Character with octal ASCII code "ooo". Because integers and characters are really the same type, you'll often see code where a character is assigned to an integer. This is considered normal in C, even though it looks a bit odd.ArraysArrays in C are declared by giving their size , where the subscripts range from 0 to (size-1). Forexample, the fragment: double vector[20] ; char name[16] ;shows the declaration of a 20-element array of doubles, vector, and a 16-elementarray of characters, name. The legal subscripts for the two arrays are 0 to 19and 0 to 15, respectively.Multiple dimension arrays (matrices) are treated as arrays of arrays in C. The following declaration definesa table of 10 character arrays, where each character array contains 16 characters: char table[10][16]To access the jth character in the ith row, you would write: table[i][j]In C, an array's name does not refer to the array's contents! Instead, the name is the addressof the first array element (0)! It is hard to over-emphasize this point, as it is the source of manysubtle C errors. Consider the following declarations: char nameA[16] ; char nameB[16] ;It is perfectly legal in C to write: if ( nameA == nameB )However, the comparison is not between the two 16-character strings, but between the addressesof the two arrays. Given that ``nameA'' and ``nameB'' are different arrays, this comparison will always be false.The rationale for this seemingly strange behavior is that it supports passing arrays by reference. When an anarray is named as an argument, a pointer is actually passed. Consider a function to change all lower-caseletters in a string to 'x', and a call to that function using nameAabove: void letter_to_X( char *string, int length ) { int i ; for ( i = 0 ; i < length ; i++ ) { if ( string[i] >= 'a' && string[i] <= 'z' ) string[i] = 'X' ; } } . . . letter_to_X( nameA, 16 ) ;There are several things to note: The argument is a pointer to a character. This is in line with the notion that an array name's value is the address of its first element. The length has to be passed in explicitly : there is no way to determine the size of an array from its address alone. The assignment string[i] = 'X' uses a subscript with a pointer. This is perfectly normal in C -- the compiler simply uses the pointer as the base address for its subscript calculations. The assignment changes the contents of .{code} nameA because we have a pointer to the array rather than a copy of the array contents. There is no protection against subscript errors. If the length argument is incorrect, or if the algorithm is wrong, it is possible to access and modify data that is not part of the array. Unlike the lists, sequences, and strings in the RogueWave library, subscript errors are not caught in C. Such errors are the source of many subtle failures in C programs.StringsIn C, character string constants are constant arrays of characters. As in C++, suchstrings are enclosed in double quotes. They are constant because the text of the string is clearly spelledout between the quotes. They are arrays , as they occupy contiguous memory, with the characters numberedfrom zero. It is even possible (if a bit silly) to subscript strings; for example: "abcdef"[3]is the character 'd'.The C (and C++) convention is that all strings are terminated by a NULL character(character '\0'). All constant strings have a NULLappended by the compiler. All strings that are constructed in character array variables should have a NULLappended. Most string manipulation functions use the NULL as a marker to terminateprocessing. If the NULL is missing, unrelated areas of memory may be modified andcorrupted.Because string constants are arrays, the constraints from the previous section apply. In particular, it is impossiblein C to assign a string constant to a character array directly, as the ``value'' of a string constant is the addressof its first character. Instead, there are "library functions" to handle stringcopying, etc., the interface to which is available via: #include <string.h>Here are a few of the common functions: char *strcpy(char *to, const char *from) Copy the string from to string to. The return value is the to pointer, which can then be passed to other functions. It is up to the caller to ensure that: The from string is properly terminated with a NULL. The compiler ensures this for string constants. The to string has enough space allocated to hold all the characters in from plus the terminating NULL ! Example (void) strcpy(nameA, "Joe Blow") ; Note that the string is copied to an array, but we already know the array name is a pointer to its first element. Also, the cast of the return value to (void) says that we know there is a return value but we're ignoring it. char *strcat(char *to, const char *from) Append string from to the end of string to. The return value is the to pointer, which can then be passed to other functions. It is up to the caller to ensure that: Both from and to are properly terminated with a NULL. The to string has enough space allocated to hold all the characters in the combined strings plus the terminating NULL. Example (void) strcat(nameA, ", Jr.") ; Adds the string ", Jr." to the end of nameA. Again, casting the return value to (void) says we're ignoring the return value. int strlen(const char *s) Returns the length of string s. Note that this is the number of characters up-to but not including the NULL byte. This may be less than the space actually allocated (for example, if a string does not fill up a character array). If the string was not terminated with a NULL, then strlen will continue scanning through memory until either it finds a NULL by coincidence or it creates a memory violation. Example if ( strlen(nameA) < 8 ) { (void) strcpy( nameB, nameA ) } The code above copies the string in nameA to nameB if the string in nameA is less than eight characters long.StructuresAs mentioned previously, a C structure is essentially a C++ class with no member functions and with all thedata members public. Indeed, if you look in the C++ reference manual, you'll see that this is .{emphasis} exactlyhow C++ defines the meaning of a .{code} struct .Most C programmers use structures to provide an approximation to objects. The object data is stored in the structure'selements, and a set of C functions is developed to manipulate such structures. The difference between C and C++is that the latter can enforce the access rules. That is, in C++ only member functions can getat the object's data. In C, it is a matter of convention and discipline as to which functions can manipulate astructure's contents.Example struct name { char first[16] ; char mi ; char last[20] ; } ; struct student { struct name stu_name ; int stu_number ; double stu_debt ; } ; struct student rit[15000] ;In the example above, structure name has three components: a 16 character array forthe first name, a single character for the middle initial, and a 20 character array for the last name. The secondstructure, student, uses the previous structure to define a component for the student'sname, as well as two other components for the student number and amount of money owed. Finally, and array of 15000student structures is defined to hold the overall RIT enrollment.As with classes, dot notation is used to select components: rit[6] The sixth element of the array (a student structure). rit[6].stu_name The name of the sixth student (a name structure). rit[6].stu_name.mi The middle initial of the sixth student's name (a char).Unlike arrays, a structure variable refers to the whole structure, not its address. When structures arepassed to functions, a copy is passed, and changes to the copy are not reflected in the original structure.To affect a structure, the function argument must be a pointer.Example void clear_debt( struct student *p_student ) { p->stu_debt = 0.0 ; return ; } . . . clear_debt( &rit[6] ) ;The function clear_debt expects a pointer to a struct student,and uses this to set the stu_debt component to zero. In the call to clear_debt,the address of operator & is used to createa pointer to the sixth RIT student.TypedefsThe need to use the struct keyword, possibly with an asterisk for a pointer, canclutter up a C program's declarations. The typedef construct lets us createsuitable aliases for any type we wishExamples typedef struct name Name ; typedef struct student Student ; typedef struct student *StudentPtr ;After these declarations, we can use the identifiers Name, Student,and StudentPtr instead of the longer forms using keywords and asterisks. For example,the array of records can be declared as: Student rit[15000] ;and the function header becomes: void clear_debt( StudentPtr p_student ) {PointersBoth C and C++ support pointers to data in memory. We've already seen a couple uses of pointers in previousexamples. What follows are some more simple examples of pointers in C, using the student records declarationsabove:Declaration struct student *p_stu ; or StudentPtr p_stu ;Assignment p_stu = &rit[6] ;Access p_stu->stu_debt = p_stu * 1.02 ;Memory AllocationIn both C and C++, pointers are used primarily to create dynamic data structures like lists and trees. C++ allocatesnew objects and recycles existing ones with new and delete,respectively. In addition, well-designed class libraries hide much of the complexity behind a simpler class interfaces.The RogueWave RWCString class, for example, provides strings that can grow and shrink.The allocation and deallocation needed to support these strings is hidden in the implementation.In C, many more of these details are visible to clients of a package built from pointers. What is more, theburden of allocating and freeing memory at the right time is on the programmer's shoulders. There is nothing likea C++ destructor in C. The following simple example will demonstrate the key memory management issues in C:The ProblemAssume we decide to replace the array implementation of RIT's student database with one based on singly linkedlists.Solution Part 1To do this, we'll define a new structure type StuNode which contains a studentstructure and a pointer to the next StuNode in the list: typedef struct stu_node *StuNodePtr ; typedef struct stu_node { Student sn_student ; StuNodePtr sn_next ; } StuNode ;Next we'll define a global pointer rit_head to point to the first student in the list. As thelist is initially empty, we'll set this pointer to zero (or NULL, a symbolic constantavailable in file stddef.h): #include <stddef.h> . . . StuNodePtr rit_head = NULL ;Solution Part 2Now we need a function to add a new student to the list (the argument is the student to add). This will requireaccess to the malloc memory allocation function, which is declared in stdlib.h.We'll assume the student is added at the list head: #include <stdlib.h> . . . void add_student( Student new_stu ) { StuNodePtr new_node ; new_node = (StuNodePtr) malloc( sizeof(StuNode) ) ; new_node->sn_student = new_stu ; new_node->sn_next = rit_head ; rit_head = new_node ; }The first assignment calls the system .{code} malloc function with the size (in bytes) of a .{code} StuNodestructure. The return value is a pointer to newly allocated memory at least as large as that requested. Unfortunately,this pointer is of type .{code} "char *" , rather than .{code} "StuNodePtr" . To remedy this,we .{term} cast the pointer from its real type to the type we want: that's the purpose of .{code} "(StuNodePtr)"in front of .{code} malloc . The remainder of the code: Copies the student structure argument into the student structure component of the node, Ensures the node points to whatever is at the head of the list, and Sets the head pointer to the newly created node.Solution Part 3Finally, we need a way to dispose of a node structure when a student is removed from the list. We won't givethe details of finding the node in the list and properly unlinking it; we'll assume we simply need to delete thespace associated with the node: void free_node( StuNodePtr p_stu ) { (void) free( (char *) p_stu ) ; }The free function is also in the standard library, and it simply releases thespace associated with pointer p_stu. We cast the pointer to type (char*), which is the type of pointer expected by free. The return valuefrom free is an integer, but this value is rarely (if ever) used. To indicatewe are ignoring the value, we cast the return value to (void). Once a memory regionif freed, no further reference to the region is allowed. If such pointer access occurs by accident, the programwill behave unpredictably.NOTE: This can happen in C++ as well if there are any pointers to deleted objects!.MiscellanyTwo other keywords that can be prepended to a declaration are extern and static. An extern declaration gives the name and type of a variable or function, but doesnot allocate any space. Such statements are typically found in header files defining the interface to a C module.Typically the space is allocated when the variable or function is defined in the .c or .Cfile that implements the module.A static function or global variable is one whose scope is restricted to the currentimplementation file. These declarations occur at the top of the source file, before any references to the associatedfunctions or variables. No other module can refer to these names, so they are effectively "hidden" withinthe implementation file where they are defined. In essence, static provides a crudeform of private data and operations.In summary, C's data structuring mechanisms are both more primitive and more unstructured than those of C++.They are primitive in that they do not support member functions, protected or private information, or generic (template)structures. They are more unstructured in that neither array subscripts nor pointers are checked for legality.The flexibility of this free-wheeling approach must be balanced against the increased probability of subtle, hardto locate bugs. The smart approach is to do as much as possible in C++, using stable, well-designed library classes.C Input/OutputC input/output is also primitive compared to C++. There are no input or output streams, nor are the >>and << I/O operators available. As with string manipulation and memory allocation,I/O is supported by a standard library, stdio.h. Access to the library interface is gainedby including its header file: #include <stdio.h>Here are a few of the functions provided. getchar() Returns the next character from standard input as an int . On end-of-file, the special indicator EOF (a negative value) is returned. Example int c ; for ( c = getchar() ; c != EOF ; c = getchar() ) { process_char( c ) ; } printf(format [,args] ) printf has a variable length argument list. The first argument is a string specifying the output format. Embedded in this string can be formatting specifiers, each preceded by a '%' The specifiers tell how to format the arguments that follow, from left to right. Example printf( "String %s integer %d float %5.2f\\n", s, i, f ) ; The first argument, s, is handled by the %s specifier. This assumes the argument points to a string of characters, which are printed until the terminating NULL is encountered. The second argument, i, is printed as a decimal integer by the .{code} "%d" specifier. Finally, the last argument, f, is printed as a floating point number by the %5.2f specifier. The "5.2" portion says to use a field 5 characters wide, and to print 2 digits to the right of the decimal point. There are many other output formats, and many other I/O functions as well. For all the details, consult the manual page for the standard I/O library: man stdio Please note that printf has no way of verifying the argument types. If you pass an integer where the format requires a pointer, you'll get weird output and possibly a core dump. You just have to be very careful.Compiling C Source FilesThe Unix convention is that files ending in .c (lower case c) contain C code,while those ending in .C (upper case C) are for C++. While we have a compiler thathandles just the C language, you are probably better off using the C++ compiler, CC,for both C and C++ files. All the programs we'll develop should compile this way, though you may get warning messagesfrom C code because the C++ compiler is pickier about type checking..NOTE: You may have to define a special .c.o rule in your Makefiles to have C code compiled by the C++ compiler. |
|