You are on page 1of 46

1

Chapter 20 - C Legacy Code Topics


Outline
20.1 Introduction
20.2 Redirecting Input/Output on UNIX and DOS Systems
20.3 Variable-Length Argument Lists
20.4 Using Command-Line Arguments
20.5 Notes on Compiling Multiple-Source-File Programs
20.6 Program Termination with exit and atexit
20.7 The volatile Type Qualifier
20.8 Suffixes for Integer and Floating-Point Constants
20.9 Signal Handling
20.10 Dynamic Memory Allocation with calloc and realloc
20.11 The Unconditional Branch: goto
20.12 Unions
20.13 Linkage Specifications

 2003 Prentice Hall, Inc. All rights reserved.


2

20.1 Introduction

• Several advanced topics in chapter

• Many capabilities specific to OS


– Especially UNIX and/or DOS

• Chapter for C++ programmers working with C


legacy code

 2003 Prentice Hall, Inc. All rights reserved.


3
20.2 Redirecting Input/Output on UNIX and
DOS Systems
• Standard I/O
– Keyboard (input) and screen (output)
– Can redirect I/O
• Inputs can come from a file, output can go to a file
• Redirect symbol (<)
– Operating system feature (not C++ feature!)
• UNIX and DOS
– $ myProgram < input
• myProgram is an executable file
• input is a data file
• $ is the command-line prompt
– Input to program now comes from file input, not the
keyboard
 2003 Prentice Hall, Inc. All rights reserved.
4
20.2 Redirecting Input/Output on UNIX and
DOS Systems
• Pipe command ( | )
– Output of one program becomes input of another
– $ firstProgram | secondProgram
– Output of firstProgram goes to secondProgram
• Redirect output ( > )
– Output of program goes to a file
– $ myProgram > myFile
• Output goes to myFile (erases previous contents)

 2003 Prentice Hall, Inc. All rights reserved.


5
20.2 Redirecting Input/Output on UNIX and
DOS Systems
• Append output (>>)
– Output of program appends to end of file
– $ myProgram >> myFile
• Output goes to end of myFile

 2003 Prentice Hall, Inc. All rights reserved.


6

20.3 Variable-Length Argument Lists

• In C++, we use function overloading


– Variable-length arguments for programmers working with C
– Create functions with unspecified number of arguments
• Function format
– Include <cstdarg>
– Use ellipsis (…) at end of parameter list
• Must be last item in parameter list
• Must be one named parameter before ellipsis
– double myFunction(int i, …);

 2003 Prentice Hall, Inc. All rights reserved.


7

20.3 Variable-Length Argument Lists

• Usage (inside function)


– Declare object of type va_list
• Holds data needed by other macros
• va_list myList;
– Run macro va_start
• First argument is va_list object
• Second is last parameter before ellipsis starts
• va_start( myList, i );

 2003 Prentice Hall, Inc. All rights reserved.


8

20.3 Variable-Length Argument Lists

• Usage
– Access arguments with macro va_arg
• First argument is va_list
• Second is the expected type of variable
• Returns the value
• myArg = va_arg( myList, double );
– Can use different data types for different arguments
– Run macro va_end
• va_end( myList );

 2003 Prentice Hall, Inc. All rights reserved.


9
1 // Fig. 20.2: fig20_02.cpp
2 // Using variable-length argument lists.
Outline
3 #include <iostream>
4
fig20_02.cpp
5 using std::cout;
(1 of 3)
6 using std::endl;
7 using std::ios;
8
9 #include <iomanip>
10
11 using std::setw;
12 using std::setprecision;
13 using std::setiosflags;
14 using std::fixed;
Note use of ellipsis in the
15
16 #include <cstdarg>
prototype, and one defined
17 argument before it.
18 double average( int, ... );
19
20 int main()
21 {
22 double double1 = 37.5;
23 double double2 = 22.5;
24 double double3 = 1.7;
25 double double4 = 10.2;
26

 2003 Prentice Hall, Inc.


All rights reserved.
10
27 cout << fixed << setprecision( 1 ) << "double1 = "
28 << double1 << "\ndouble2 = " << double2 << "\ndouble3 = "
Outline
29 << double3 << "\ndouble4 = " << double4 << endl
30 << setprecision( 3 )
fig20_02.cpp
31 << "\nThe average of double1 and double2 is "
(2 of 3)
32 << average( 2, double1, double2 )
33 << "\nThe average of double1, double2, and double3 is "
34 << average( 3, double1, double2, double3 )
35 << "\nThe average of double1, double2, double3"
36 << " and double4 is "
37 << average( 4, double1, double2, double3, double4 )
38 << endl;
39
Call function with a variable
40 return 0;
number of arguments (passing
41
42 } // end main
the number of arguments as a
43 parameter).

 2003 Prentice Hall, Inc.


All rights reserved.
11
44 // calculate average
45 double average( int count, ... ) Create a va_list object and
Outline
46 { call macro va_start.
47 double total = 0; count is the parameter fig20_02.cpp
48 va_list list; // for storing information
before the needed
ellipsis.by va_start (3 of 3)
49
50 va_start( list, count );
51 Extract each argument from
52 // process variable length argument list list, treat as a double.
53 for ( int i = 1; i <= count; i++ )
54 total += va_arg( list, double );
55
56 // end the va_start
End the macros, helps with a
57 va_end( list );
normal function return.
58
59 return total / count;
60
61 } // end function average

 2003 Prentice Hall, Inc.


All rights reserved.
12
double1 = 37.5
double2 = 22.5
Outline
double3 = 1.7
double4 = 10.2
fig20_02.cpp
 
output (1 of 1)
The average of double1 and double2 is 30.000
The average of double1, double2, and double3 is 20.567
The average of double1, double2, double3 and double4 is 17.975

 2003 Prentice Hall, Inc.


All rights reserved.
13

20.4 Using Command-Line Arguments

• Can pass arguments to main in UNIX/DOS


– Include parameters in main
• int main( int argc, char *argv[] )
– int argc
• Number of arguments
– char *argv[]
• Array of strings that contains command-line arguments
– Example: $ copy input output
argc: 3
argv[0]: "copy"
argv[1]: "input"
argv[2]: "output"

 2003 Prentice Hall, Inc. All rights reserved.


14

20.4 Using Command-Line Arguments

• Upcoming example
– Program to copy input file to output file
– copy input output
– Read a character from file input and write to file output
• Stop when no more characters to read (EOF)

 2003 Prentice Hall, Inc. All rights reserved.


15
1 // Fig. 20.3: fig20_03.cpp
2 // Using command-line arguments
Outline
3 #include <iostream>
4
fig20_03.cpp
5 using std::cout;
(1 of 2)
6 using std::endl;
7 using std::ios;
8
9 #include <fstream>
10
11 using std::ifstream;
Notice parameters in main.
12 using std::ofstream;
13
14 int main( int argc, char *argv[] )
15 {
16 // check number of command-line arguments
17 if ( argc != 3 )
18
argv[1] is the input
cout << "Usage: copyFile infile_name outfile_name" << endl;
file --
19 open for reading.
20 else {
21 ifstream inFile( argv[ 1 ], ios::in );
22
23 // input file could not be opened
24 if ( !inFile ) {
25 cout << argv[ 1 ] << " could not be opened" << endl;
26 return -1;
27
28 } // end if
 2003 Prentice Hall, Inc.
All rights reserved.
16
29
30 ofstream outFile( argv[ 2 ], ios::out );
Outline
31 argv[2] is the output file --
32 // output file could not be opened open for writing. fig20_03.cpp
33 if ( !outFile ) {
(2 of 2)
34 cout << argv[ 2 ] << " could not be opened" << endl;
35 inFile.close();
36 return -2;
37
38 } // end if
39 Read a character from
40 char c = inFile.get(); // read characterand write to
first inFile,
41 outFile. Loop stops when
42 while ( inFile ) { EOF reached.
43 outFile.put( c ); // output character
44 c = inFile.get(); // read next character
45
46 } // end while
47 } // end else
48
49 return 0;
50
51 } // end main

 2003 Prentice Hall, Inc.


All rights reserved.
17
20.5 Notes on Compiling Multiple-Source-File
Programs
• Program with multiple source files
– Function definition must be entirely in one file
• Cannot be split up into multiple files
– Global variables accessible to functions in same file
• Must be defined in every file they are used
• Use extern to access global variable in another file
– Indicates variable defined later in file or in another file
– Example
• int myGlobal; (defined in file1)
• extern int myGlobal; (appears in file2)

 2003 Prentice Hall, Inc. All rights reserved.


18
20.5 Notes on Compiling Multiple-Source-File
Programs
• Function prototypes
– Can be used in other files, extern not needed
– Include prototype in each file function used
• Compile files together
– Prototype indicates function defined later in same file, or in
another file
– Example: loading header files
• #include <cstring>
• Contains prototypes of functions
• We do not need to know where definitions are

 2003 Prentice Hall, Inc. All rights reserved.


19
20.5 Notes on Compiling Multiple-Source-File
Programs
• Keyword static
– In context of global variables/functions
– Can only be used by functions in same file
• Internal linkage
• Globals/functions have external linkage by default
– Used with utility functions called only in one file
– For functions
• If defined before used, include static in definition
• Otherwise, use with prototype
• Makefiles
– make - utility to aid compilation and linking
– Saves effort of constantly recompiling for minor changes

 2003 Prentice Hall, Inc. All rights reserved.


20

20.6 Program Termination with exit and atexit

• Function exit
– Forces program to end
– Usually takes EXIT_SUCCESS or EXIT_FAILURE
• Symbolic constants (#define)
• exit(EXIT_SUCCESS);
– Returns value to environment, indicating success or failure
• Exact value varies with system

 2003 Prentice Hall, Inc. All rights reserved.


21

20.6 Program Termination with exit and atexit

• Function atexit
– Takes pointer to function (function name)
• atexit( myFunction )
• Functions must take void, return void
– Registers function to run when program ends successfully
• When exit called, or when main terminates
• atexit does not terminate the program
– Can register up to 32 functions
• Use multiple atexit calls
• Called in reverse order of registration

 2003 Prentice Hall, Inc. All rights reserved.


22
1 // Fig. 20.4: fig20_04.cpp
2 // Using the exit and atexit functions
Outline
3 #include <iostream>
4
fig20_04.cpp
5 using std::cout;
(1 of 2)
6 using std::endl;
7 using std::cin;
8
9 #include <cstdlib>
10
11 void print(); Register print to be called
12
when the program terminates.
13 int main()
14 {
print must return void and
15 atexit( print );
take no arguments.
// register function print
16
17 cout << "Enter 1 to terminateprint will
program be called
with if theexit"
function
18 program
<< "\nEnter 2 to terminate endsnormally\n";
program successfully.
19
20 int answer;
21 cin >> answer;
22

 2003 Prentice Hall, Inc.


All rights reserved.
23
23 // exit if answer is 1
24 if ( answer == 1 ) {
Outline
25 cout << "\nTerminating program with function exit\n";
26 exit( EXIT_SUCCESS );
fig20_04.cpp
27
(2 of 2)
28 } // end if Call function exit, passing a
29 symbolic constant.
30 cout << "\nTerminating program by reaching the end of main"
31 << endl;
32
33 return 0;
34
35 } // end main
36
37 // display message before termination
38 void print()
39 {
40 cout << "Executing function print at program termination\n"
41 << "Program terminated" << endl;
42
43 } // end function print

 2003 Prentice Hall, Inc.


All rights reserved.
24
Enter 1 to terminate program with function exit
Enter 2 to terminate program normally
Outline
2
 
fig20_04.cpp
Terminating program by reaching the end of main
output (1 of 1)
Executing function print at program termination
Program terminated

Enter 1 to terminate program with function exit


Enter 2 to terminate program normally
1
 
Terminating program with function exit
Executing function print at program termination
Program terminated

 2003 Prentice Hall, Inc.


All rights reserved.
25

20.7 The volatile Type Qualifier

• volatile qualifier
– Indicates variable may be altered outside of program
– Variable not under control of program
• Compiler cannot perform certain optimizations

 2003 Prentice Hall, Inc. All rights reserved.


26
20.8 Suffixes for Integer and Floating-Point
Constants
• C++ has suffixes for constants
– Integer suffixes
• u or U (unsigned)
• l or L (long)
• ul or UL (unsigned long)
• Without suffix, uses smallest type that can hold number
• Examples: 174u, 1322L, 7364ul
– Floating point suffixes
• f or F (float)
• l or L (long double)
• Without suffix, double
• Examples: 3.14159L, 1.28f
– Incorrect suffix is compiler error

 2003 Prentice Hall, Inc. All rights reserved.


27

20.9 Signal Handling

• Signal
– Unexpected event, can terminate program
• Interrupts (ctrl-c)
• Illegal instructions
• Floating-point exceptions (division by zero)
• Function signal traps unexpected signals
– <csignal>
– Takes signal number (symbolic constants defined)
– Takes pointer to function (function name)
• Signal handler passed signal number
– May be required to call signal again inside handler
• Depends on system
• Reinitialize handler after it handles signal
 2003 Prentice Hall, Inc. All rights reserved.
28

20.9 Signal Handling

Signal Explanation

SIGABRT Abnormal termination of the program


(such as a call to abort).
SIGFPE An erroneous arithmetic operation,
such as a divide by zero or an
operation resulting in overflow.
SIGILL Detection of an illegal instruction.
SIGINT Receipt of an interactive attention
signal.
SIGSEGV An invalid access to storage.
SIGTERM A termination request sent to the
program.

 2003 Prentice Hall, Inc. All rights reserved.


29

20.9 Signal Handling

• Function raise
– Takes signal number
– Creates signal

 2003 Prentice Hall, Inc. All rights reserved.


30
1 // Fig. 20.6: fig20_06.cpp
2 // Using signal handling
Outline
3 #include <iostream>
4
fig20_06.cpp
5 using std::cout;
(1 of 3)
6 using std::cin;
7 using std::endl;
8
9 #include <iomanip>
10
11 using std::setw;
12
13 #include <csignal>
14 #include <cstdlib>
15 #include <ctime>
16
17 void signalHandler( int );
18
Register signalHandler to deal
19 int main() with SIGINT events.
20 {
21 signal( SIGINT, signalHandler );
22 srand( time( 0 ) );
23

 2003 Prentice Hall, Inc.


All rights reserved.
31
24 // create and output random numbers
25 for ( int i = 1; i <= 100; i++ ) {
Outline
26 int x = 1 + rand() % 50; Note call to function raise.
27
fig20_06.cpp
28 // raise SIGINT when x is 25
(2 of 3)
29 if ( x == 25 )
30 raise( SIGINT );
31
32 cout << setw( 4 ) << i;
33
34 // output endl when i is a multiple of 10
35 if ( i % 10 == 0 )
36 cout << endl;
37
38 } // end for
39
40 return 0;
41
42 } // end main
43

 2003 Prentice Hall, Inc.


All rights reserved.
32
44 // handles signal
45 void signalHandler( int signalValue )
Outline
46 {
47 cout << "\nInterrupt signal (" << signalValue
fig20_06.cpp
48 << ") received.\n"
(3 of 3)
49 << "Do you wish to continue (1 = yes or 2 = no)? ";
50
51 int response;
52
53 cin >> response;
54
55 // check for invalid responses
56 while ( response != 1 && response != 2 ) {
57 cout << "(1 = yes or 2 = no)? ";
58 cin >> response;
59
60 } // end while
61
62 // determine if it is time to exit
63 if ( response != 1 ) May be required to
64 exit( EXIT_SUCCESS );
reinitialize.
65
66 // call signal and pass it SIGINT and address of signalHandler
67 signal( SIGINT, signalHandler );
68
69 } // end function signalHandler

 2003 Prentice Hall, Inc.


All rights reserved.
33
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
Outline
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
fig20_06.cpp
41 42 43 44 45 46 47 48 49 50
output (1 of 1)
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99
Interrupt signal (2) received.
Do you wish to continue (1 = yes or 2 = no)? 1
100

1 2 3 4
Interrupt signal (2) received.
Do you wish to continue (1 = yes or 2 = no)? 2

 2003 Prentice Hall, Inc.


All rights reserved.
34
20.10 Dynamic Memory Allocation with calloc
and realloc
• Dynamic memory allocation
– Can create dynamic arrays
• Function calloc
– void *calloc(size_t nelmt, size_t size)
• nelmt - number of elements in array
• size - size of each element
– Returns pointer to dynamic array
• Elements initialized to 0

 2003 Prentice Hall, Inc. All rights reserved.


35
20.10 Dynamic Memory Allocation with calloc
and realloc
• Function realloc
– Resizes dynamic object
• Data not modified if size increased
• If shrunk, beginning the same
– void *realloc(void *ptr, size_t newSize)
• ptr - pointer to object being reallocated
• newSize - new size of the object
• If ptr == 0, acts like malloc
• If newSize == 0 and ptr != 0, memory freed
– Returns pointer to reallocated memory (NULL if no space)

 2003 Prentice Hall, Inc. All rights reserved.


36

20.11 The Unconditional Branch: goto

• Unstructured programming
– Use when performance crucial
• Using break to exit loop
– goto statement
• goto label;
• Program jumps to first statement after label
• Label is an identifier and colon (start:)
– Quick escape from deeply nested loop
• goto start;

 2003 Prentice Hall, Inc. All rights reserved.


37
1 // Fig. 20.7: fig20_07.cpp
2 // Using goto.
Outline
3 #include <iostream>
4
fig20_07.cpp
5 using std::cout;
(1 of 2)
6 using std::endl;
7
8 #include <iomanip>
9
10 using std::left;
11 using std::setw;
12
13 int main()
Notice declaration of label
14 {
start
15 int count = 1;
16
17 start: // label
18
19 // goto end when count exceeds 10
20 if ( count > 10 )
21 goto end;
22
23 cout << setw( 2 ) << left << count;
24 ++count; Note the format of the goto
25 statement.
26 // goto start on line 17
27 goto start;

 2003 Prentice Hall, Inc.


All rights reserved.
38
28
29 end: // label
Outline
30
31 cout << endl;
fig20_07.cpp
32
(2 of 2)
33 return 0;
34
35 } // end main fig20_07.cpp
output (1 of 1)
1 2 3 4 5 6 7 8 9 10

 2003 Prentice Hall, Inc.


All rights reserved.
39

20.12 Unions

• Union
– Memory that contains a variety of objects
• Data members share space
• Only contains one data member at a time
– Conserves storage
– Only the last data member defined can be accessed
– Declaration same as class or struct
union Number {
int x;
float y;
} ;
Union myObject;

 2003 Prentice Hall, Inc. All rights reserved.


40

20.12 Unions

• Union operations
– Assignment to union of same type: =
– Taking address: &
– Accessing union members: .
– Accessing members using pointers: ->

 2003 Prentice Hall, Inc. All rights reserved.


41

20.12 Unions

• Anonymous unions
– No type name
– Does not create a type; creates an unnamed object
• Contains only public data members
– Data members accessed like normal variables
• Use name, no . or -> required
– If declared globally, must be static
– Example
union {

int integer1;

double double1;

char *charPtr;

}; // end anonymous union

integer1 = 3;

 2003 Prentice Hall, Inc. All rights reserved.


42
1 // Fig. 20.8: fig20_08.cpp
2 // An example of a union.
Outline
3 #include <iostream>
4
fig20_08.cpp
5 using std::cout;
(1 of 2)
6 using std::endl; Create a named union with
7 two data members. They share
8 // define union Number
the same memory.
9 union Number {
10 int integer1;
11 double double1;
12
13 }; // end union Number
14
15 int main()
16 {
17 Number value; // union variable
18
19 value.integer1 = 100; // assign 100 to member integer1
20
This will print the integer
21 cout << "Put a value in the integer member\n" 100 as a double.
22 << "and print both members.\nint: "
23 << value.integer1 << "\ndouble: " << value.double1 The program output is
24 << endl; implementation dependent,
25 but will show how ints and
doubles are represented
differently.
 2003 Prentice Hall, Inc.
All rights reserved.
43
26 value.double1 = 100.0; // assign 100.0 to member double1
27
Outline
28 cout << "Put a value in the floating member\n"
29 << "and print both members.\nint: "
fig20_08.cpp
30 << value.integer1 << "\ndouble: " << value.double1
(2 of 2)
31 << endl;
32
33 return 0; fig20_08.cpp
34 output (1 of 1)
35 } // end main

Put a value in the integer member


and print both members.
int: 100
double: -9.25596e+061
Put a value in the floating member
and print both members.
int: 0
double: 100

 2003 Prentice Hall, Inc.


All rights reserved.
44
1 // Fig. 20.9: fig20_09.cpp
2 // Using an anonymous union.
Outline
3 #include <iostream>
4
fig20_09.cpp
5 using std::cout;
(1 of 2)
6 using std::endl;
7
8 int main()
9 { Create an anonymous union.
10 // declare an anonymous union
The data members can be
11 // members integer1, double1 and charPtr share the same space
accessed without using a
12 union {
13 int integer1;
union name.
14 double double1;
15 char *charPtr;
16
17 }; // end anonymous union
18
19 // declare local variables
20 int integer2 = 1;
21 double double2 = 3.3;
22 char *char2Ptr = "Anonymous";
23

 2003 Prentice Hall, Inc.


All rights reserved.
45
24 // assign value to each union member
25 // successively and print each
Outline
26 cout << integer2 << ' ';
27 integer1 = 2;
fig20_09.cpp
28 cout << integer1 << endl;
(2 of 2)
29
30 cout << double2 << ' ';
31 double1 = 4.4; fig20_09.cpp
32 cout << double1 << endl; output (1 of 1)
33
34 cout << char2Ptr << ' ';
35 charPtr = "union";
36 cout << charPtr << endl;
37
38 return 0;
39
40 } // end main

1 2
3.3 4.4
Anonymous union

 2003 Prentice Hall, Inc.


All rights reserved.
46

20.13 Linkage Specifications

• Can call compiled C functions from C++ program


– However, C does not encode function names like C++
– Leads to problems linking
• Linkage specifications
– To link properly, tell compiler that function compiled in C
– For single functions
extern "C" function prototype
– For multiple functions
extern "C"
{
function prototypes
}

 2003 Prentice Hall, Inc. All rights reserved.

You might also like