Transcript Document

1
Chapter 20 - C Legacy Code Topics
Outline
20.1
20.2
20.3
20.4
20.5
20.6
20.7
20.8
20.9
20.10
20.11
20.12
20.13
Introduction
Redirecting Input/Output on UNIX and DOS Systems
Variable-Length Argument Lists
Using Command-Line Arguments
Notes on Compiling Multiple-Source-File Programs
Program Termination with exit and atexit
The volatile Type Qualifier
Suffixes for Integer and Floating-Point Constants
Signal Handling
Dynamic Memory Allocation with calloc and realloc
The Unconditional Branch: goto
Unions
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Fig. 20.2: fig20_02.cpp
// Using variable-length argument lists.
#include <iostream>
9
Outline
fig20_02.cpp
(1 of 3)
using std::cout;
using std::endl;
using std::ios;
#include <iomanip>
using
using
using
using
std::setw;
std::setprecision;
std::setiosflags;
std::fixed;
#include <cstdarg>
Note use of ellipsis in the
prototype, and one defined
argument before it.
double average( int, ... );
int main()
{
double double1
double double2
double double3
double double4
=
=
=
=
37.5;
22.5;
1.7;
10.2;
 2003 Prentice Hall, Inc.
All rights reserved.
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
cout <<
<<
<<
<<
<<
<<
<<
<<
<<
<<
<<
<<
fixed << setprecision( 1 ) << "double1 = "
double1 << "\ndouble2 = " << double2 << "\ndouble3 = "
double3 << "\ndouble4 = " << double4 << endl
setprecision( 3 )
"\nThe average of double1 and double2 is "
average( 2, double1, double2 )
"\nThe average of double1, double2, and double3 is "
average( 3, double1, double2, double3 )
"\nThe average of double1, double2, double3"
" and double4 is "
average( 4, double1, double2, double3, double4 )
endl;
return 0;
}
// end main
10
Outline
fig20_02.cpp
(2 of 3)
Call function with a variable
number of arguments (passing
the number of arguments as a
parameter).
 2003 Prentice Hall, Inc.
All rights reserved.
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// calculate average
Create a va_list object and
double average( int count, ... )
{
call macro va_start.
double total = 0;
count is the parameter
va_list list; // for storing information needed by va_start
before the ellipsis.
11
Outline
fig20_02.cpp
(3 of 3)
va_start( list, count );
// process variable length argument list
for ( int i = 1; i <= count; i++ )
total += va_arg( list, double );
// end the va_start
va_end( list );
Extract each argument from
list, treat as a double.
End the macros, helps with a
normal function return.
return total / count;
}
// end function average
 2003 Prentice Hall, Inc.
All rights reserved.
double1
double2
double3
double4
=
=
=
=
37.5
22.5
1.7
10.2
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
12
Outline
fig20_02.cpp
output (1 of 1)
 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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
15
// Fig. 20.3: fig20_03.cpp
// Using command-line arguments
#include <iostream>
Outline
fig20_03.cpp
(1 of 2)
using std::cout;
using std::endl;
using std::ios;
#include <fstream>
using std::ifstream;
using std::ofstream;
Notice parameters in main.
int main( int argc, char *argv[] )
{
// check number of command-line arguments
if ( argc != 3 )
argv[1] is the
cout << "Usage: copyFile infile_name outfile_name" << endl;
input file --
open for reading.
else {
ifstream inFile( argv[ 1 ], ios::in );
// input file could not be opened
if ( !inFile ) {
cout << argv[ 1 ] << " could not be opened" << endl;
return -1;
}
// end if
 2003 Prentice Hall, Inc.
All rights reserved.
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
16
Outline
ofstream outFile( argv[ 2 ], ios::out );
// output file could not be opened
if ( !outFile ) {
cout << argv[ 2 ] << " could not be opened"
inFile.close();
return -2;
argv[2] is the output file -open for writing.
fig20_03.cpp
(2 of 2)
<< endl;
} // end if
char c = inFile.get(); // read
while ( inFile ) {
outFile.put( c );
c = inFile.get();
}
Read a character from
firstinFile,
character
and write to
outFile. Loop stops when
EOF reached.
// output character
// read next character
} // end while
// end else
return 0;
}
// end main
 2003 Prentice Hall, Inc.
All rights reserved.
17
20.5 Notes on Compiling Multiple-SourceFile 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-SourceFile 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-SourceFile 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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Fig. 20.4: fig20_04.cpp
// Using the exit and atexit functions
#include <iostream>
22
Outline
fig20_04.cpp
(1 of 2)
using std::cout;
using std::endl;
using std::cin;
#include <cstdlib>
void print();
int main()
{
atexit( print );
//
Register print to be called
when the program terminates.
print must return void and
take no function
arguments.print
register
print
willwith
be called
if theexit"
cout << "Enter 1 to terminate
program
function
<< "\nEnter 2 to terminate
program
program
endsnormally\n";
successfully.
int answer;
cin >> answer;
 2003 Prentice Hall, Inc.
All rights reserved.
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// exit if answer is 1
if ( answer == 1 ) {
cout << "\nTerminating program with function exit\n";
exit( EXIT_SUCCESS );
}
// end if
Call function exit, passing a
symbolic constant.
23
Outline
fig20_04.cpp
(2 of 2)
cout << "\nTerminating program by reaching the end of main"
<< endl;
return 0;
}
// end main
// display message before termination
void print()
{
cout << "Executing function print at program termination\n"
<< "Program terminated" << endl;
}
// end function print
 2003 Prentice Hall, Inc.
All rights reserved.
Enter 1 to terminate program with function exit
Enter 2 to terminate program normally
2
Terminating program by reaching the end of main
Executing function print at program termination
Program terminated
24
Outline
fig20_04.cpp
output (1 of 1)
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).
An erroneous arithmetic operation,
such as a divide by zero or an
operation resulting in overflow.
Detection of an illegal instruction.
Receipt of an interactive attention
signal.
An invalid access to storage.
A termination request sent to the
program.
SIGFPE
SIGILL
SIGINT
SIGSEGV
SIGTERM
 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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
30
// Fig. 20.6: fig20_06.cpp
// Using signal handling
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
Outline
fig20_06.cpp
(1 of 3)
#include <iomanip>
using std::setw;
#include <csignal>
#include <cstdlib>
#include <ctime>
void signalHandler( int );
int main()
{
signal( SIGINT, signalHandler );
srand( time( 0 ) );
Register signalHandler to deal
with SIGINT events.
 2003 Prentice Hall, Inc.
All rights reserved.
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// create and output random numbers
for ( int i = 1; i <= 100; i++ ) {
int x = 1 + rand() % 50;
31
Outline
Note call to function raise.
// raise SIGINT when x is 25
if ( x == 25 )
raise( SIGINT );
fig20_06.cpp
(2 of 3)
cout << setw( 4 ) << i;
// output endl when i is a multiple of 10
if ( i % 10 == 0 )
cout << endl;
}
// end for
return 0;
}
// end main
 2003 Prentice Hall, Inc.
All rights reserved.
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// handles signal
void signalHandler( int signalValue )
{
cout << "\nInterrupt signal (" << signalValue
<< ") received.\n"
<< "Do you wish to continue (1 = yes or 2 = no)? ";
32
Outline
fig20_06.cpp
(3 of 3)
int response;
cin >> response;
// check for invalid responses
while ( response != 1 && response != 2 ) {
cout << "(1 = yes or 2 = no)? ";
cin >> response;
}
// end while
// determine if it is time to exit
if ( response != 1 )
exit( EXIT_SUCCESS );
May be required to
reinitialize.
// call signal and pass it SIGINT and address of signalHandler
signal( SIGINT, signalHandler );
}
// end function signalHandler
 2003 Prentice Hall, Inc.
All rights reserved.
1
2
3
4
5
6
7
8
9
33
10
11 12 13 14 15 16 17 18 19
21 22 23 24 25 26 27 28 29
31 32 33 34 35 36 37 38 39
41 42 43 44 45 46 47 48 49
51 52 53 54 55 56 57 58 59
61 62 63 64 65 66 67 68 69
71 72 73 74 75 76 77 78 79
81 82 83 84 85 86 87 88 89
91 92 93 94 95 96 97 98 99
Interrupt signal (2) received.
Do you wish to continue (1 = yes or 2
100
20
30
40
50
60
70
80
90
Outline
fig20_06.cpp
output (1 of 1)
= no)? 1
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
37
// Fig. 20.7: fig20_07.cpp
// Using goto.
#include <iostream>
Outline
fig20_07.cpp
(1 of 2)
using std::cout;
using std::endl;
#include <iomanip>
using std::left;
using std::setw;
int main()
{
int count = 1;
start:
Notice declaration of label
start
// label
// goto end when count exceeds 10
if ( count > 10 )
goto end;
cout << setw( 2 ) << left << count;
Note the
++count;
format of the goto
statement.
// goto start on line 17
goto start;
 2003 Prentice Hall, Inc.
All rights reserved.
28
29
30
31
32
33
34
35
1
38
end:
Outline
// label
cout << endl;
fig20_07.cpp
(2 of 2)
return 0;
}
2
// end main
3
4
5
6
7
8
9
10
fig20_07.cpp
output (1 of 1)
 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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
42
// Fig. 20.8: fig20_08.cpp
// An example of a union.
#include <iostream>
using std::cout;
using std::endl;
// define union Number
union Number {
int integer1;
double double1;
};
Outline
Create a named union with
two data members. They
share the same memory.
fig20_08.cpp
(1 of 2)
// end union Number
int main()
{
Number value;
// union variable
value.integer1 = 100;
cout <<
<<
<<
<<
// assign 100 to member integer1
"Put a value in the integer member\n"
"and print both members.\nint:
"
value.integer1 << "\ndouble: " << value.double1
endl;
This will print the integer
100 as a double.
The program output is
implementation dependent,
but will show how ints and
doubles are represented
differently.
 2003 Prentice Hall, Inc.
All rights reserved.
26
27
28
29
30
31
32
33
34
35
value.double1 = 100.0;
cout <<
<<
<<
<<
// assign 100.0 to member double1
"Put a value in the floating member\n"
"and print both members.\nint:
"
value.integer1 << "\ndouble: " << value.double1
endl;
return 0;
}
43
Outline
fig20_08.cpp
(2 of 2)
fig20_08.cpp
output (1 of 1)
// 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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Fig. 20.9: fig20_09.cpp
// Using an anonymous union.
#include <iostream>
using std::cout;
using std::endl;
44
Outline
fig20_09.cpp
(1 of 2)
int main()
{
Create an anonymous union.
// declare an anonymous union
The data members can be
// members integer1, double1 and charPtr share the same space
accessed without using a
union {
union name.
int integer1;
double double1;
char *charPtr;
};
// end anonymous union
// declare local variables
int integer2 = 1;
double double2 = 3.3;
char *char2Ptr = "Anonymous";
 2003 Prentice Hall, Inc.
All rights reserved.
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// assign value to each union member
// successively and print each
cout << integer2 << ' ';
integer1 = 2;
cout << integer1 << endl;
cout << double2 << ' ';
double1 = 4.4;
cout << double1 << endl;
45
Outline
fig20_09.cpp
(2 of 2)
fig20_09.cpp
output (1 of 1)
cout << char2Ptr << ' ';
charPtr = "union";
cout << charPtr << endl;
return 0;
}
// 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.