<<

Chapter 1: Introducing Chapter 1: Introducing C Origins of C • By 1971, Ritchie began to develop an extended version of B. Chapter 1 • He called his language NB (“New B”) first. • As the language began to diverge from B, he changed its name to C. Introducing C • The language was stable enough by 1973 that could be rewritten in C.

1 Copyright © 2008 W. W. Norton & Company. 3 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 1: Introducing C Chapter 1: Introducing C Origins of C Standardization of C • C is a by-product of UNIX, developed at Bell • K& C Laboratories by Ken Thompson, Dennis Ritchie, – Described in Kernighan and Ritchie, The C Programming and others. Language (1978) – De facto standard • Thompson designed a small language named B. • C89/C90 • B was based on BCPL, a systems programming – ANSI standard X3.159-1989 (completed in 1988; formally language developed in the mid-1960s. approved in December 1989) – International standard ISO/IEC 9899:1990 • – International standard ISO/IEC 9899:1999 – Incorporates changes from Amendment 1 (1995)

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 1: Introducing C Chapter 1: Introducing C C-Based Languages Strengths of C • C++ includes all the features of C, but adds • Efficiency classes and other features to support object- • Portability oriented programming. • Power • Java is based on C++ and therefore inherits many • Flexibility C features. • Standard library • C# is a more recent language derived from C++ and Java. • Integration with UNIX • has adopted many of the features of C.

5 Copyright © 2008 W. W. Norton & Company. 7 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 1: Introducing C Chapter 1: Introducing C Properties of C Weaknesses of C • Low-level • Programs can be error-prone. • Small • Programs can be difficult to understand. • Permissive • Programs can be difficult to modify.

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 1: Introducing C Chapter 2: C Fundamentals Effective Use of C Program: Printing a Pun • Learn how to avoid pitfalls. #include • Use software tools (lint, debuggers) to int main(void) { programs more reliable. ("To C, or not to C: that is the question.\n"); • Take advantage of existing code libraries. return 0; } • Adopt a sensible set of coding conventions. • This program might be stored in a named pun.c. • Avoid “tricks” and overly complex code. • The file name doesn’t matter, but the .c extension is • Stick to the standard. often required.

9 Copyright © 2008 W. W. Norton & Company. 2 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals Compiling and Linking • Before a program can be executed, three steps are usually necessary: – Preprocessing. The preprocessor obeys commands that Chapter 2 begin with # (known as directives) – Compiling. A compiler translates then translates the C Fundamentals program into machine instructions (object code). – Linking. A linker combines the object code produced by the compiler with any additional code needed to yield a complete executable program. • The preprocessor is usually integrated with the compiler.

1 Copyright © 2008 W. W. Norton & Company. 3 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Compiling and Linking Using cc The GCC Compiler • To compile and the pun.c program under • GCC is one of the most popular C compilers. UNIX, enter the following command in a terminal • GCC is supplied with Linux but is available for or command-line window: many other platforms as well. % cc pun.c • Using this compiler is similar to using cc: The % character is the UNIX prompt. % gcc -o pun pun.c • Linking is automatic when using cc; no separate link command is necessary.

4 Copyright © 2008 W. W. Norton & Company. 6 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals Compiling and Linking Using cc Integrated Development Environments • After compiling and linking the program, cc • An integrated development environment (IDE) is leaves the executable program in a file named a software package that makes it possible to edit, a.out by default. compile, link, execute, and debug a program • The -o option lets us choose the name of the file without leaving the environment. containing the executable program. • The following command causes the executable version of pun.c to be named pun: % cc -o pun pun.c

5 Copyright © 2008 W. W. Norton & Company. 7 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals The General Form of a Simple Program Directives • Simple C programs have the form • Before a C program is compiled, it is first edited directives by a preprocessor. • Commands intended for the preprocessor are int main(void) { called directives. statements • Example: } #include is a header containing information about C’s standard I/O library.

8 Copyright © 2008 W. W. Norton & Company. 10 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals The General Form of a Simple Program Directives • C uses { and } in much the same way that some • Directives always begin with a # character. other languages use words like begin and end. • By default, directives are one line long; there’s no • Even the simplest C programs rely on three key semicolon or other special marker at the end. language features: – Directives – Functions – Statements

9 Copyright © 2008 W. W. Norton & Company. 11 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Functions Statements • A function is a series of statements that have been • A statement is a command to be executed when grouped together and given a name. the program runs. • Library functions are provided as part of the C • pun.c uses only two kinds of statements. One is implementation. the return statement; the other is the function • A function that computes a value uses a return call. statement to specify what value it “returns”: • Asking a function to perform its assigned task is return x + 1; known as calling the function. • pun.c calls printf to display a string: printf("To C, or not to C: that is the question.\n");

12 Copyright © 2008 W. W. Norton & Company. 14 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals The main Function Statements • The main function is mandatory. • C requires that each statement end with a • main is special: it gets called automatically when semicolon. the program is executed. – There’s one exception: the compound statement. • main returns a status code; the value 0 indicates • Directives are normally one line long, and they normal program termination. don’t end with a semicolon. • If there’s no return statement at the end of the main function, many compilers will produce a warning message.

13 Copyright © 2008 W. W. Norton & Company. 15 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Printing Comments • When the printf function displays a string • A comment begins with /* and end with */. literal—characters enclosed in double quotation /* This is a comment */ marks—it doesn’t show the quotation marks. • Comments may appear almost anywhere in a • printf doesn’t automatically advance to the program, either on separate lines or on the same next output line when it finishes printing. lines as other program text. • To make printf advance one line, include \n • Comments may extend over more than one line. (the new-line character) in the string to be /* Name: pun.c printed. Purpose: Prints a bad pun. Author: K. N. King */

16 Copyright © 2008 W. W. Norton & Company. 18 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals Printing Strings Comments • The statement • Warning: Forgetting to terminate a comment may cause printf("To C, or not to C: that is the question.\n"); the compiler to ignore part of your program: could be replaced by two calls of printf: printf("My "); /* forgot to close this comment... printf(" "); printf("To C, or not to C: "); printf("has "); /* so it ends here */ printf("that is the question.\n"); printf("fleas"); • The new-line character can appear more than once in a : printf("Brevity is the soul of wit.\n --Shakespeare\n");

17 Copyright © 2008 W. W. Norton & Company. 19 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Comments in C99 Types • In C99, comments can also be written in the • Every variable must have a . following way: • C has a wide variety of types, including int and // This is a comment float. • This style of comment ends automatically at the • A variable of type int (short for integer) can end of a line. store a whole number such as 0, 1, 392, or –2553. • Advantages of // comments: – The largest int value is typically 2,147,483,647 but – Safer: there’s no chance that an unterminated comment can be as small as 32,767. will accidentally consume part of a program. – Multiline comments stand out better.

20 Copyright © 2008 W. W. Norton & Company. 22 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals Variables and Assignment Types • Most programs need to a way to store data • A variable of type float (short for floating- temporarily during program execution. point) can store much larger numbers than an int • These storage locations are called variables. variable. • Also, a float variable can store numbers with digits after the decimal point, like 379.125. • Drawbacks of float variables: – Slower arithmetic – Approximate nature of float values

21 Copyright © 2008 W. W. Norton & Company. 23 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Declarations Assignment • Variables must be declared before they are used. • A variable can be given a value by means of • Variables can be declared one at a : assignment: int height; height = 8; float profit; The number 8 is said to be a constant. • Alternatively, several can be declared at the same • Before a variable can be assigned a value—or time: used in any other way—it must first be declared. int height, length, width, volume; float profit, loss;

24 Copyright © 2008 W. W. Norton & Company. 26 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals Declarations Assignment • When main contains declarations, these must • A constant assigned to a float variable usually precede statements: contains a decimal point: int main(void) profit = 2150.48; { • It’s best to append the letter f to a floating-point declarations constant if it is assigned to a float variable: statements } profit = 2150.48f; • In C99, declarations don’t have to come before Failing to include the f may cause a warning from statements. the compiler.

25 Copyright © 2008 W. W. Norton & Company. 27 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Assignment Printing the Value of a Variable • An int variable is normally assigned a value of • printf can be used to display the current value type int, and a float variable is normally of a variable. assigned a value of type float. • To the message • Mixing types (such as assigning an int value to a Height: h float variable or assigning a float value to an where h is the current value of the height int variable) is possible but not always safe. variable, we’ use the following call of printf: printf("Height: %d\n", height); •%dis a placeholder indicating where the value of height is to be filled in.

28 Copyright © 2008 W. W. Norton & Company. 30 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals Assignment Printing the Value of a Variable • Once a variable has been assigned a value, it can •%dworks only for int variables; to print a be used to help compute the value of another float variable, use %f instead. variable: • By default, %f displays a number with six digits height = 8; after the decimal point. length = 12; • To force %f to display p digits after the decimal width = 10; volume = height * length * width; point, put .p between % and f. /* volume is now 960 */ • To print the line • The right side of an assignment can be a formula Profit: $2150.48 (or expression, in C terminology) involving use the following call of printf: constants, variables, and operators. printf("Profit: $%.2f\n", profit);

29 Copyright © 2008 W. W. Norton & Company. 31 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Program: Computing the Printing the Value of a Variable Dimensional Weight of a Box • There’s no limit to the number of variables that can • Division is represented by / in C, so the obvious way be printed by a single call of printf: to compute the dimensional weight would be printf("Height: %d Length: %d\n", height, length); weight = volume / 166; • In C, however, when one integer is divided by another, the answer is “truncated”: all digits after the decimal point are lost. – The volume of a 12” ×10” ×8” box will be 960 cubic inches. – Dividing by 166 gives 5 instead of 5.783.

32 Copyright © 2008 W. W. Norton & Company. 34 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals Program: Computing the Program: Computing the Dimensional Weight of a Box Dimensional Weight of a Box • Shipping companies often charge extra for boxes that • One solution is to add 165 to the volume before are large but very light, basing the fee on volume dividing by 166: instead of weight. weight = (volume + 165) / 166; • The usual method to compute the “dimensional • A volume of 166 would give a weight of 331/166, weight” is to divide the volume by 166 (the allowable or 1, while a volume of 167 would yield 332/166, number of cubic inches per pound). or 2. • The dweight.c program computes the dimensional weight of a particular box: Dimensions: 12x10x8 Volume (cubic inches): 960 Dimensional weight (pounds): 6

33 Copyright © 2008 W. W. Norton & Company. 35 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals dweight.c Initialization /* Computes the dimensional weight of a 12" x 10" x 8" box */

#include • The initial value of a variable may be included in int main(void) its declaration: { int height, length, width, volume, weight; int height = 8;

height = 8; The value 8 is said to be an initializer. length = 12; width = 10; • Any number of variables can be initialized in the volume = height * length * width; weight = (volume + 165) / 166; same declaration:

printf("Dimensions: %dx%dx%d\n", length, width, height); int height = 8, length = 12, width = 10; printf("Volume (cubic inches): %d\n", volume); printf("Dimensional weight (pounds): %d\n", weight); • Each variable requires its own initializer. return 0; int height, length, width = 10; } /* initializes only width */

36 Copyright © 2008 W. W. Norton & Company. 38 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals Initialization Printing Expressions • Some variables are automatically set to zero when • printf can display the value of any numeric a program begins to execute, but most are not. expression. • A variable that doesn’t have a default value and • The statements hasn’t yet been assigned a value by the program is volume = height * length * width; said to be uninitialized. printf("%d\n", volume); • Attempting to access the value of an uninitialized could be replaced by variable may yield an unpredictable result. printf("%d\n", height * length * width); • With some compilers, worse behavior—even a program crash—may occur.

37 Copyright © 2008 W. W. Norton & Company. 39 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Program: Computing the Dimensional Reading Input Weight of a Box (Revisited) • scanf is the C library’s counterpart to printf. • dweight2.c is an improved version of the • scanf requires a format string to specify the dimensional weight program in which the user appearance of the input data. enters the dimensions. • Example of using scanf to read an int value: • Each call of scanf is immediately preceded by a scanf("%d", &i); call of printf that displays a prompt. /* reads an integer; stores into i */ • The & symbol is usually (but not always) required when using scanf.

40 Copyright © 2008 W. W. Norton & Company. 42 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals Reading Input dweight2.c /* Computes the dimensional weight of a box from input provided by the user */

• Reading a float value requires a slightly #include

different call of scanf: int main(void) { scanf("%f", &x); int height, length, width, volume, weight; • "%f" scanf printf("Enter height of box: "); tells to look for an input value in scanf("%d", &height); float format (the number may contain a decimal printf("Enter length of box: "); scanf("%d", &length); point, but doesn’t have to). printf("Enter width of box: "); scanf("%d", &width); volume = height * length * width; weight = (volume + 165) / 166;

printf("Volume (cubic inches): %d\n", volume); printf("Dimensional weight (pounds): %d\n", weight);

return 0; }

41 Copyright © 2008 W. W. Norton & Company. 43 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Program: Computing the Dimensional Defining Names for Constants Weight of a Box (Revisited) • Sample output of program: • When a program is compiled, the preprocessor replaces Enter height of box: 8 each macro by the value that it represents. Enter length of box: 12 • During preprocessing, the statement Enter width of box: 10 weight = (volume + INCHES_PER_POUND - 1) / INCHES_PER_POUND; Volume (cubic inches): 960 will become Dimensional weight (pounds): 6 weight = (volume + 166 - 1) / 166; • Note that a prompt shouldn’t end with a new-line character.

44 Copyright © 2008 W. W. Norton & Company. 46 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals Defining Names for Constants Defining Names for Constants • dweight.c and dweight2.c rely on the • The value of a macro can be an expression: constant 166, whose meaning may not be clear to #define RECIPROCAL_OF_PI (1.0f / 3.14159f) someone reading the program. • If it contains operators, the expression should be • Using a feature known as macro definition, we enclosed in parentheses. can name this constant: • Using only upper-case letters in macro names is a #define INCHES_PER_POUND 166 common convention.

45 Copyright © 2008 W. W. Norton & Company. 47 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Program: Converting from Program: Converting from Fahrenheit to Celsius Fahrenheit to Celsius • The celsius.c program prompts the user to • Defining SCALE_FACTOR to be (5.0f / 9.0f) enter a Fahrenheit temperature; it then prints the instead of (5 / 9) is important. equivalent Celsius temperature. • Note the use of %.1f to display celsius with • Sample program output: just one digit after the decimal point. Enter Fahrenheit temperature: 212 Celsius equivalent: 100.0 • The program will allow temperatures that aren’t integers.

48 Copyright © 2008 W. W. Norton & Company. 50 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals celsius.c Identifiers /* Converts a Fahrenheit temperature to Celsius */ #include • Names for variables, functions, macros, and other #define FREEZING_PT 32.0f entities are called identifiers. #define SCALE_FACTOR (5.0f / 9.0f) • An identifier may contain letters, digits, and int main(void) underscores, but must begin with a letter or { float fahrenheit, celsius; underscore: printf("Enter Fahrenheit temperature: "); times10 get_next_char _done scanf("%f", &fahrenheit); It’s usually best to avoid identifiers that begin with celsius = (fahrenheit - FREEZING_PT) * SCALE_FACTOR; an underscore. printf("Celsius equivalent: %.1f\n", celsius); return 0; • Examples of illegal identifiers: } 10times get-next-char

49 Copyright © 2008 W. W. Norton & Company. 51 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Identifiers Keywords • C is case-sensitive: it distinguishes between • The following keywords can’t be used as upper-case and lower-case letters in identifiers. identifiers: • For example, the following identifiers are all auto enum restrict* unsigned break extern return void different: case float short volatile job joB jOb jOB Job JoB JOb JOB char for signed while const goto sizeof _Bool* continue if static _Complex* default inline* struct _Imaginary* do int switch double long typedef else register union *C99 only

52 Copyright © 2008 W. W. Norton & Company. 54 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals Identifiers Keywords • Many programmers use only lower-case letters in • Keywords (with the exception of _Bool, identifiers (other than macros), with underscores _Complex, and _Imaginary) must be written inserted for legibility: using only lower-case letters. symbol_table current_page name_and_address • Names of library functions (e.g., printf) are • Other programmers use an upper-case letter to also lower-case. begin each word within an identifier: symbolTable currentPage nameAndAddress • C places no limit on the maximum length of an identifier.

53 Copyright © 2008 W. W. Norton & Company. 55 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Layout of a C Program Layout of a C Program • A C program is a series of tokens. • The amount of space between tokens usually isn’t critical. • Tokens include: • At one extreme, tokens can be crammed together with no – Identifiers space between them, except where this would cause two – Keywords tokens to merge: – Operators /* Converts a Fahrenheit temperature to Celsius */ #include – Punctuation #define FREEZING_PT 32.0f – Constants #define SCALE_FACTOR (5.0f/9.0f) int main(void){float fahrenheit,celsius;printf( – String literals "Enter Fahrenheit temperature: ");scanf("%f", &fahrenheit); celsius=(fahrenheit-FREEZING_PT)*SCALE_FACTOR; printf("Celsius equivalent: %.1f\n", celsius);return 0;}

56 Copyright © 2008 W. W. Norton & Company. 58 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 2: C Fundamentals Layout of a C Program Layout of a C Program • The statement • The whole program can’t be put on one line, printf("Height: %d\n", height); because each preprocessing directive requires a consists of seven tokens: separate line. printf Identifier • Compressing programs in this fashion isn’t a good ( Punctuation idea. "Height: %d\n" String literal • In fact, adding spaces and blank lines to a program , Punctuation can make it easier to read and understand. height Identifier ) Punctuation ; Punctuation

57 Copyright © 2008 W. W. Norton & Company. 59 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 2: C Fundamentals Chapter 2: C Fundamentals Layout of a C Program Layout of a C Program • C allows any amount of space—blanks, tabs, and • Putting a space inside a string literal is allowed, new-line characters—between tokens. although it changes the meaning of the string. • Consequences for program layout: • Putting a new-line character in a string (splitting – Statements can be divided over any number of lines. the string over two lines) is illegal: – Space between tokens (such as before and after each printf("To C, or not to C: operator, and after each comma) makes it easier for the that is the question.\n"); eye to separate them. /*** WRONG ***/ – Indentation can make nesting easier to spot. – Blank lines can divide a program into logical units.

60 Copyright © 2008 W. W. Norton & Company. 62 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 2: C Fundamentals Chapter 3: Formatted Input/Output Layout of a C Program • Although extra spaces can be added between tokens, it’s not possible to add space within a token without changing the meaning of the program or causing an error. Chapter 3 • Writing fl oat fahrenheit, celsius; /*** WRONG ***/ Formatted Input/Output or fl oat fahrenheit, celsius; /*** WRONG ***/ produces an error when the program is compiled.

61 Copyright © 2008 W. W. Norton & Company. 1 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output The printf Function The printf Function • The printf function must be supplied with a format • Compilers aren’t required to check that the string, followed by any values that are to be inserted number of conversion specifications in a format into the string during printing: string matches the number of output items. printf(string, expr1, expr2, …); • Too many conversion specifications: • The format string may contain both ordinary printf("%d %d\n", i); /*** WRONG ***/ characters and conversion specifications, which begin with the % character. • Too few conversion specifications: • A conversion specification is a placeholder printf("%d\n", i, j); /*** WRONG ***/ representing a value to be filled in during printing. –%dis used for int values –%fis used for float values

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output The printf Function The printf Function • Ordinary characters in a format string are printed as they • Compilers aren’t required to check that a appear in the string; conversion specifications are replaced. conversion specification is appropriate. • Example: • If the programmer uses an incorrect specification, int i, j; float x, y; the program will produce meaningless output:

i = 10; printf("%f %d\n", i, x); /*** WRONG ***/ j = 20; x = 43.2892f; y = 5527.0f;

printf("i = %d, j = %d, x = %f, y = %f\n", i, j, x, y); • Output: i = 10, j = 20, x = 43.289200, y = 5527.000000

3 Copyright © 2008 W. W. Norton & Company. 5 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output Conversion Specifications Conversion Specifications • A conversion specification can have the form %m.pX • The meaning of the precision, p, depends on the or %-m.pX, where m and p are integer constants and choice of X, the conversion specifier. X is a letter. • The d specifier is used to display an integer in • Both m and p are optional; if p is omitted, the period decimal form. that separates m and p is also dropped. – p indicates the minimum number of digits to display • In the conversion specification %10.2f, m is 10, p is (extra zeros are added to the beginning of the number if 2, and X is f. necessary). • In the specification %10f, m is 10 and p (along with – If p is omitted, it is assumed to be 1. the period) is missing, but in the specification %.2f, p is 2 and m is missing.

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output Conversion Specifications Conversion Specifications • The minimum field width, m, specifies the minimum • Conversion specifiers for floating-point numbers: number of characters to print. e — Exponential format. p indicates how many digits • If the value to be printed requires fewer than m characters, should appear after the decimal point (the default is 6). If p it is right-justified within the field. is 0, no decimal point is displayed. – %4d displays the number 123 as •123. (• represents the f — “Fixed decimal” format. p has the same meaning as space character.) for the e specifier. • If the value to be printed requires more than m characters, g — Either exponential format or fixed decimal format, the field width automatically expands to the necessary size. depending on the number’s size. p indicates the maximum • Putting a minus sign in front of m causes left justification. number of significant digits to be displayed. The g – The specification %-4d would display 123 as 123•. conversion won’t show trailing zeros. If the number has no digits after the decimal point, g doesn’t display the decimal point.

7 Copyright © 2008 W. W. Norton & Company. 9 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output Program: Using printf to Format Numbers Escape Sequences • The tprintf.c program uses printf to • The \n code that used in format strings is called display integers and floating-point numbers in an . various formats. • Escape sequences enable strings to contain nonprinting (control) characters and characters that have a special meaning (such as "). • A partial list of escape sequences: Alert (bell) \a Backspace \b New line \n Horizontal tab \t

10 Copyright © 2008 W. W. Norton & Company. 12 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output tprintf.c Escape Sequences /* Prints int and float values in various formats */

#include • A string may contain any number of escape int main(void) sequences: { printf("Item\tUnit\tPurchase\n\tPrice\tDate\n"); int i; float x; • Executing this statement prints a two-line heading: i = 40; x = 839.21f; Item Unit Purchase printf("|%d|%5d|%-5d|%5.3d|\n", i, i, i, i); Price Date printf("|%10.3f|%10.3e|%-10g|\n", x, x, x); return 0; } • Output: |40| 40|40 | 040| | 839.210| 8.392e+02|839.21 |

11 Copyright © 2008 W. W. Norton & Company. 13 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output Escape Sequences The scanf Function • Another common escape sequence is \", which • In many cases, a will contain represents the " character: only conversion specifications: printf("\"Hello!\""); int i, j; /* prints "Hello!" */ float x, y; • To print a single \ character, put two \ characters scanf("%d%d%f%f", &i, &j, &x, &y); in the string: • Sample input: printf("\\"); 1 -20 .3 -4.0e3 /* prints one \ character */ scanf will assign 1, –20, 0.3, and –4000.0 to i, j, x, and y, respectively.

14 Copyright © 2008 W. W. Norton & Company. 16 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output The scanf Function The scanf Function • scanf reads input according to a particular • When using scanf, the programmer must check format. that the number of conversion specifications • A scanf format string may contain both ordinary matches the number of input variables and that characters and conversion specifications. each conversion is appropriate for the • The conversions allowed with scanf are corresponding variable. essentially the same as those used with printf. • Another trap involves the & symbol, which normally precedes each variable in a scanf call. • The & is usually (but not always) required, and it’s the programmer’s responsibility to remember to use it.

15 Copyright © 2008 W. W. Norton & Company. 17 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output How scanf Works How scanf Works • scanf tries to match groups of input characters • When asked to read an integer, scanf first with conversion specifications in the format string. searches for a digit, a plus sign, or a minus sign; it • For each conversion specification, scanf tries to then reads digits until it reaches a nondigit. locate an item of the appropriate type in the input • When asked to read a floating-point number, data, skipping blank space if necessary. scanf looks for • scanf then reads the item, stopping when it – a plus or minus sign (optional), followed by – digits (possibly containing a decimal point), followed by reaches a character that can’t belong to the item. – an exponent (optional). An exponent consists of the – If the item was read successfully, scanf continues letter e (or E), an optional sign, and one or more digits. processing the rest of the format string. •%e, %f, and %g are interchangeable when used – If not, scanf returns immediately. with scanf.

18 Copyright © 2008 W. W. Norton & Company. 20 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output How scanf Works How scanf Works • As it searches for a number, scanf ignores white-space • When scanf encounters a character that can’t be characters (space, horizontal and vertical tab, form-feed, and part of the current item, the character is “put back” new-line). to be read again during the scanning of the next • A call of scanf that reads four numbers: scanf("%d%d%f%f", &i, &j, &x, &y); input item or during the next call of scanf. • The numbers can be on one line or spread over several lines: 1 -20 .3 -4.0e3 • scanf sees a stream of characters (¤ represents new-line): ••1¤-20•••.3¤•••-4.0e3¤ ssrsrrrsssrrssssrrrrrr (s = skipped; r = read) • scanf “peeks” at the final new-line without reading it.

19 Copyright © 2008 W. W. Norton & Company. 21 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output How scanf Works Ordinary Characters in Format Strings • Sample input: • Examples: 1-20.3-4.0e3¤ – If the format string is "%d/%d" and the input is • The call of scanf is the same as before: •5/•96, scanf succeeds. – If the input is •5•/•96 , scanf fails, because the / scanf("%d%d%f%f", &i, &j, &x, &y); in the format string doesn’t match the space in the • Here’s how scanf would process the new input: input. –%d. Stores 1 into i and puts the - character back. • To allow spaces after the first number, use the –%d. Stores –20 into j and puts the . character back. format string "%d /%d" instead. –%f. Stores 0.3 into x and puts the - character back. –%f. Stores –4.0 × 103 into y and puts the new-line character back.

22 Copyright © 2008 W. W. Norton & Company. 24 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output Ordinary Characters in Format Strings Confusing printf with scanf • When it encounters one or more white-space • Although calls of scanf and printf may characters in a format string, scanf reads white- appear similar, there are significant differences space characters from the input until it reaches a between the two. non-white-space character (which is “put back”). • One common mistake is to put & in front of • When it encounters a non-white-space character in variables in a call of printf: a format string, scanf compares it with the next printf("%d %d\n", &i, &j); /*** WRONG ***/ input character. – If they match, scanf discards the input character and continues processing the format string. – If they don’t match, scanf puts the offending character back into the input, then aborts.

23 Copyright © 2008 W. W. Norton & Company. 25 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output Confusing printf with scanf Program: Adding Fractions • Incorrectly assuming that scanf format strings • The addfrac.c program prompts the user to should resemble printf format strings is another enter two fractions and then displays their . common error. • Sample program output: • Consider the following call of scanf: Enter first fraction: 5/6 scanf("%d, %d", &i, &j); Enter second fraction: 3/4 – scanf will first look for an integer in the input, which The sum is 38/24 it stores in the variable i. – scanf will then try to match a comma with the next input character. – If the next input character is a space, not a comma, scanf will terminate without reading a value for j.

26 Copyright © 2008 W. W. Norton & Company. 28 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 3: Formatted Input/Output Chapter 3: Formatted Input/Output Confusing printf with scanf addfrac.c /* Adds two fractions */

• Putting a new-line character at the end of a #include scanf format string is usually a bad idea. int main(void) • To scanf, a new-line character in a format string { int num1, denom1, num2, denom2, result_num, result_denom; is equivalent to a space; both cause scanf to printf("Enter first fraction: "); advance to the next non-white-space character. scanf("%d/%d", &num1, &denom1);

• If the format string is "%d\n", scanf will skip printf("Enter second fraction: "); white space, read an integer, then skip to the next scanf("%d/%d", &num2, &denom2); result_num = num1 * denom2 + num2 *denom1; non-white-space character. result_denom = denom1 * denom2; • A format string like this can cause an interactive printf("The sum is %d/%d\n",result_num, result_denom) program to “hang.” return 0; }

27 Copyright © 2008 W. W. Norton & Company. 29 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 4: Expressions Arithmetic Operators • C provides five binary arithmetic operators: + addition - subtraction Chapter 4 * multiplication / division % remainder Expressions • An operator is binary if it has two operands. • There are also two unary arithmetic operators: + unary plus - unary minus

1 Copyright © 2008 W. W. Norton & Company. 3 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 4: Expressions Chapter 4: Expressions Operators Unary Arithmetic Operators • C emphasizes expressions rather than statements. • The unary operators require one operand: • Expressions are built from variables, constants, i = +1; and operators. j = -i; • C has a rich collection of operators, including • The unary + operator does nothing. It’s used – arithmetic operators primarily to emphasize that a numeric constant is – relational operators positive. – logical operators – assignment operators – increment and decrement operators and many others

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 4: Expressions Binary Arithmetic Operators Implementation-Defined Behavior • The value of i%jis the remainder when i is • The C standard deliberately leaves parts of the divided by j. language unspecified. 10%3has the value 1, and 12%4has the value 0. • Leaving parts of the language unspecified reflects • Binary arithmetic operators—with the exception C’s emphasis on efficiency, which often means of %—allow either integer or floating-point matching the way that hardware behaves. operands, with mixing allowed. • It’s best to avoid writing programs that depend on • When int and float operands are mixed, the implementation-defined behavior. result has type float. 9 + 2.5f has the value 11.5, and 6.7f / 2 has the value 3.35.

5 Copyright © 2008 W. W. Norton & Company. 7 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 4: Expressions Chapter 4: Expressions The / and % Operators Operator Precedence • The / and % operators require special care: • Does i+j*kmean “add i and j, then multiply – When both operands are integers, / “truncates” the result. the result by k” or “multiply j and k, then add The value of 1/2is 0, not 0.5. i”? – The % operator requires integer operands; if either • One solution to this problem is to add parentheses, operand is not an integer, the program won’t compile. writing either (i+j)*kor i+(j*k). – Using zero as the right operand of either / or % causes undefined behavior. • If the parentheses are omitted, C uses operator – The behavior when / and % are used with negative precedence rules to determine the meaning of the operands is implementation-defined in C89. expression. – In C99, the result of a division is always truncated toward zero and the value of i%jhas the same sign as i.

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 4: Expressions Operator Precedence Operator Associativity • The arithmetic operators have the following • An operator is right associative if it groups from relative precedence: right to left. Highest: +-(unary) • The unary arithmetic operators (+ and -) are both */% right associative, so +- Lowest: (binary) -+i is equivalent to -(+i) • Examples: i+j*k is equivalent to i+(j*k) -i*-j is equivalent to (-i) * (-j) +i+j/k is equivalent to (+i) + (j / k)

9 Copyright © 2008 W. W. Norton & Company. 11 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 4: Expressions Chapter 4: Expressions Operator Associativity Program: Computing a UPC Check Digit • Associativity comes into play when an expression • Most goods sold in U.S. and Canadian stores are contains two or more operators with equal marked with a Universal Product Code (UPC): precedence. • An operator is said to be left associative if it groups from left to right. • Meaning of the digits underneath the bar code: • The binary arithmetic operators (*, /, %, +, and -) First digit: Type of item are all left associative, so First group of five digits: Manufacturer Second group of five digits: Product (including package size) i-j–k is equivalent to (i-j)-k Final digit: Check digit, used to help identify an error in the i*j/k is equivalent to (i*j)/k preceding digits

10 Copyright © 2008 W. W. Norton & Company. 12 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 4: Expressions Program: Computing a UPC Check Digit Program: Computing a UPC Check Digit • How to compute the check digit: • The upc.c program asks the user to enter the first Add the first, third, fifth, seventh, ninth, and eleventh 11 digits of a UPC, then displays the corresponding digits. check digit: Add the second, fourth, sixth, eighth, and tenth digits. Enter the first (single) digit: 0 Multiply the first sum by 3 and add it to the second sum. Enter first group of five digits: 13800 Subtract 1 from the total. Enter second group of five digits: 15173 Compute the remainder when the adjusted total is divided Check digit: 5 by 10. Subtract the remainder from 9. • The program reads each digit group as five one-digit numbers. • To read single digits, we’ll use scanf with the %1d conversion specification.

13 Copyright © 2008 W. W. Norton & Company. 15 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 4: Expressions Chapter 4: Expressions Program: Computing a UPC Check Digit upc.c /* Computes a Universal Product Code check digit */

• Example for UPC 0 13800 15173 5: #include First sum: 0 + 3 + 0 + 1 + 1 + 3 = 8. int main(void) { Second sum: 1 + 8 + 0 + 5 + 7 = 21. int d, i1, i2, i3, i4, i5, j1, j2, j3, j4, j5, Multiplying the first sum by 3 and adding the second first_sum, second_sum, total; yields 45. printf("Enter the first (single) digit: "); scanf("%1d", &d); Subtracting 1 gives 44. printf("Enter first group of five digits: "); scanf("%1d%1d%1d%1d%1d", &i1, &i2, &i3, &i4, &i5); Remainder upon dividing by 10 is 4. printf("Enter second group of five digits: "); Remainder is subtracted from 9. scanf("%1d%1d%1d%1d%1d", &j1, &j2, &j3, &j4, &j5); first_sum = d + i2 + i4 + j1 + j3 + j5; Result is 5. second_sum = i1 + i3 + i5 + j2 + j4; total = 3 * first_sum + second_sum;

printf("Check digit: %d\n", 9 - ((total - 1) % 10));

return 0; }

14 Copyright © 2008 W. W. Norton & Company. 16 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 4: Expressions Assignment Operators Simple Assignment • Simple assignment: used for storing a value into a • If v and e don’t have the same type, then the value variable of e is converted to the type of v as the assignment • Compound assignment: used for updating a value takes place: already stored in a variable int i; float f;

i = 72.99f; /* i is now 72 */ f = 136; /* f is now 136.0 */

17 Copyright © 2008 W. W. Norton & Company. 19 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 4: Expressions Chapter 4: Expressions Simple Assignment Simple Assignment • The effect of the assignment v = e is to evaluate • In many programming languages, assignment is a the expression e and copy its value into v. statement; in C, however, assignment is an • e can be a constant, a variable, or a more operator, just like +. complicated expression: • The value of an assignment v = e is the value of v i = 5; /* i is now 5 */ after the assignment. j = i; /* j is now 5 */ – The value of i = 72.99f is 72 (not 72.99). k = 10 * i + j; /* k is now 55 */

18 Copyright © 2008 W. W. Norton & Company. 20 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 4: Expressions Side Effects Side Effects • An operators that modifies one of its operands is • Watch out for unexpected results in chained said to have a side effect. assignments as a result of type conversion: • The simple assignment operator has a side effect: int i; it modifies its left operand. float f; • Evaluating the expression i=0produces the f = i = 33.3f; result 0 and—as a side effect—assigns 0 to i. •iis assigned the value 33, then f is assigned 33.0 (not 33.3).

21 Copyright © 2008 W. W. Norton & Company. 23 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 4: Expressions Chapter 4: Expressions Side Effects Side Effects • Since assignment is an operator, several • An assignment of the form v = e is allowed assignments can be chained together: wherever a value of type v would be permitted: i = j = k = 0; i = 1; • The = operator is right associative, so this k = 1 + (j = i); printf("%d %d %d\n", i, j, k); assignment is equivalent to /* prints "1 1 2" */ i = (j = (k = 0)); • “Embedded assignments” can make programs hard to read. • They can also be a source of subtle bugs.

22 Copyright © 2008 W. W. Norton & Company. 24 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 4: Expressions Lvalues Compound Assignment • The assignment operator requires an lvalue as its • Assignments that use the old value of a variable to left operand. compute its new value are common. • An lvalue represents an object stored in computer • Example: memory, not a constant or the result of a i = i + 2; computation. • Using the += compound assignment operator, we • Variables are lvalues; expressions such as 10 or simply write: 2*iare not. i += 2; /* same as i = i + 2; */

25 Copyright © 2008 W. W. Norton & Company. 27 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 4: Expressions Chapter 4: Expressions Lvalues Compound Assignment • Since the assignment operator requires an lvalue • There are nine other compound assignment operators, as its left operand, it’s illegal to put any other kind including the following: of expression on the left side of an assignment -= *= /= %= expression: • All compound assignment operators work in much the 12 = i; /*** WRONG ***/ same way: i + j = 0; /*** WRONG ***/ v += e adds v to e, storing the result in v -i = j; /*** WRONG ***/ v -= e subtracts e from v, storing the result in v • The compiler will produce an error message such v *= e multiplies v by e, storing the result in v as “invalid lvalue in assignment.” v /= e divides v by e, storing the result in v v %= e computes the remainder when v is divided by e, storing the result in v

26 Copyright © 2008 W. W. Norton & Company. 28 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 4: Expressions Compound Assignment Increment and Decrement Operators • v += e isn’t “equivalent” to v = v + e. • Two of the most common operations on a variable • One problem is operator precedence: i*=j+k are “incrementing” (adding 1) and “decrementing” isn’t the same as i=i*j+k. (subtracting 1): • There are also rare cases in which v += e differs i = i + 1; j = j - 1; from v = v + e because v itself has a side effect. • Incrementing and decrementing can be done using • Similar remarks apply to the other compound the compound assignment operators: assignment operators. i += 1; j -= 1;

29 Copyright © 2008 W. W. Norton & Company. 31 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 4: Expressions Chapter 4: Expressions Compound Assignment Increment and Decrement Operators • When using the compound assignment operators, • C provides special ++ (increment) and -- be careful not to switch the two characters that (decrement) operators. make up the operator. • The ++ operator adds 1 to its operand. The -- • Although i=+jwill compile, it is equivalent to operator subtracts 1. i = (+j), which merely copies the value of j • The increment and decrement operators are tricky into i. to use: – They can be used as prefix operators (++i and –-i) or postfix operators (i++ and i--). – They have side effects: they modify the values of their operands.

30 Copyright © 2008 W. W. Norton & Company. 32 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 4: Expressions Increment and Decrement Operators Increment and Decrement Operators • Evaluating the expression ++i (a “pre-increment”) • The -- operator has similar properties: yields i+1and—as a side effect—increments i: i = 1; printf("i is %d\n", --i); /* prints "i is 0" */ i = 1; printf("i is %d\n", i); /* prints "i is 0" */ printf("i is %d\n", ++i); /* prints "i is 2" */ i = 1; printf("i is %d\n", i); /* prints "i is 2" */ printf("i is %d\n", i--); /* prints "i is 1" */ • Evaluating the expression i++ (a “post-increment”) printf("i is %d\n", i); /* prints "i is 0" */ produces the result i, but causes i to be incremented afterwards: i = 1; printf("i is %d\n", i++); /* prints "i is 1" */ printf("i is %d\n", i); /* prints "i is 2" */

33 Copyright © 2008 W. W. Norton & Company. 35 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 4: Expressions Chapter 4: Expressions Increment and Decrement Operators Increment and Decrement Operators • ++i means “increment i immediately,” while • When ++ or -- is used more than once in the same i++ means “use the old value of i for now, but expression, the result can often be hard to understand. increment i later.” • Example: i = 1; • How much later? The C standard doesn’t specify a j = 2; precise time, but it’s safe to assume that i will be k = ++i + j++; incremented before the next statement is executed. The last statement is equivalent to i = i + 1; k = i + j; j = j + 1; The final values of i, j, and k are 2, 3, and 4, respectively.

34 Copyright © 2008 W. W. Norton & Company. 36 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 4: Expressions Increment and Decrement Operators Expression Evaluation • In contrast, executing the statements • The table can be used to add parentheses to an expression i = 1; that lacks them. j = 2; • Starting with the operator with highest precedence, put k = i++ + j++; parentheses around the operator and its operands. will give i, j, and k the values 2, 3, and 3, • Example: a = b += c++ - d + --e / -f respectively. Precedence level a = b += (c++) - d + --e / -f 1 a = b += (c++) - d + (--e) / (-f) 2 a = b += (c++) - d + ((--e) / (-f)) 3 a = b += (((c++) - d) + ((--e) / (-f))) 4 (a = (b += (((c++) - d) + ((--e) / (-f))))) 5

37 Copyright © 2008 W. W. Norton & Company. 39 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 4: Expressions Chapter 4: Expressions Expression Evaluation Order of Subexpression Evaluation • Table of operators discussed so far: • The value of an expression may depend on the Precedence Name Symbol(s) Associativity order in which its subexpressions are evaluated. ++ 1 increment (postfix) left • C doesn’t define the order in which decrement (postfix) -- 2 increment (prefix) ++ right subexpressions are evaluated (with the exception decrement (prefix) -- of subexpressions involving the logical and, unary plus + logical or, conditional, and comma operators). unary minus - • In the expression (a + b) * (c - d) we don’t * / % 3 multiplicative left know whether (a+b)will be evaluated before 4 additive + - left 5 assignment = *= /= %= += -= right (c - d).

38 Copyright © 2008 W. W. Norton & Company. 40 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 4: Expressions Order of Subexpression Evaluation Order of Subexpression Evaluation • Most expressions have the same value regardless • To prevent problems, it’s a good idea to avoid of the order in which their subexpressions are using the assignment operators in subexpressions. evaluated. • Instead, use a series of separate assignments: • However, this may not be true when a a = 5; subexpression modifies one of its operands: b = a + 2; a = 5; a = 1; c = (b = a + 2) - (a = 1); c = b - a; • The effect of executing the second statement is The value of c will always be 6. undefined.

41 Copyright © 2008 W. W. Norton & Company. 43 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 4: Expressions Chapter 4: Expressions Order of Subexpression Evaluation Order of Subexpression Evaluation • Avoid writing expressions that access the value of • Besides the assignment operators, the only a variable and also modify the variable elsewhere operators that modify their operands are increment in the expression. and decrement. • Some compilers may produce a warning message • When using these operators, be careful that an such as “operation on ‘a’ may be undefined” expression doesn’t depend on a particular order of when they encounter such an expression. evaluation.

42 Copyright © 2008 W. W. Norton & Company. 44 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 4: Expressions Order of Subexpression Evaluation Expression Statements • Example: • C has the unusual rule that any expression can be i = 2; used as a statement. j = i * i++; • Example: • It’s natural to assume that j is assigned 4. ++i; However, j could just as well be assigned 6 i is first incremented, then the new value of i is instead: fetched but then discarded. 1. The second operand (the original value of i) is fetched, then i is incremented. 2. The first operand (the new value of i) is fetched. 3. The new and old values of i are multiplied, yielding 6.

45 Copyright © 2008 W. W. Norton & Company. 47 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 4: Expressions Chapter 4: Expressions Undefined Behavior Expression Statements • Statements such as c = (b = a + 2) - (a = 1); • Since its value is discarded, there’s little point in and j=i*i++;cause undefined behavior. using an expression as a statement unless the • Possible effects of undefined behavior: expression has a side effect: – The program may behave differently when compiled i = 1; /* useful */ with different compilers. i--; /* useful */ i * j - 1; /* not useful */ – The program may not compile in the first place. – If it compiles it may not run. – If it does run, the program may crash, behave erratically, or produce meaningless results. • Undefined behavior should be avoided.

46 Copyright © 2008 W. W. Norton & Company. 48 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 4: Expressions Chapter 5: Selection Statements Expression Statements Statements • A slip of the finger can easily create a “do- • So far, we’ve used return statements and nothing” expression statement. expression statements. • For example, instead of entering • Most of C’s remaining statements fall into three i = j; categories: – Selection statements: if and switch we might accidentally type – Iteration statements: while, do, and for i + j; – Jump statements: break, continue, and goto. • Some compilers can detect meaningless (return also belongs in this category.) expression statements; you’ll get a warning such • Other C statements: as “statement with no effect.” – Compound statement – Null statement

49 Copyright © 2008 W. W. Norton & Company. 2 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements Logical Expressions • Several of C’s statements must the value of an expression to see if it is “true” or “false.” Chapter 5 • For example, an if statement might need to test the expression i

1 Copyright © 2008 W. W. Norton & Company. 3 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements Relational Operators Relational Operators • C’s relational operators: • The expression < less than i < j < k > greater than is legal, but does not test whether j lies between i <= less than or equal to and k. >= greater than or equal to < • These operators produce 0 (false) or 1 (true) when • Since the operator is left associative, this used in expressions. expression is equivalent to (i < j) < k • The relational operators can be used to compare integers and floating-point numbers, with The 1 or 0 produced by i

4 Copyright © 2008 W. W. Norton & Company. 6 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements Relational Operators Equality Operators • The precedence of the relational operators is lower • C provides two equality operators: than that of the arithmetic operators. == equal to – For example, i + j

5 Copyright © 2008 W. W. Norton & Company. 7 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements Logical Operators Logical Operators • More complicated logical expressions can be built • Both && and || perform “short-circuit” evaluation: from simpler ones by using the logical operators: they first evaluate the left operand, then the right one. ! logical negation • If the value of the expression can be deduced from the && logical and left operand alone, the right operand isn’t evaluated. || logical or • Example: • The ! operator is unary, while && and || are (i != 0) && (j / i > 0) binary. (i != 0) is evaluated first. If i isn’t equal to 0, then • The logical operators produce 0 or 1 as their result. (j / i > 0) is evaluated. • The logical operators treat any nonzero operand as • If i is 0, the entire expression must be false, so there’s no need to evaluate (j/i>0). Without short-circuit a true value and any zero operand as a false value. evaluation, division by zero would have occurred.

8 Copyright © 2008 W. W. Norton & Company. 10 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements Logical Operators Logical Operators • Behavior of the logical operators: • Thanks to the short-circuit nature of the && and ! has the value 1 if expr has the value 0. || operators, side effects in logical expressions expr1 && expr2 has the value 1 if the values of expr1 and may not always occur. expr2 are both nonzero. • Example: expr1 || expr2 has the value 1 if either expr1 or expr2 (or i > 0 && ++j > 0 both) has a nonzero value. If i>0is false, then ++j > 0 is not evaluated, so • In all other cases, these operators produce the j isn’t incremented. value 0. • The problem can be fixed by changing the condition to ++j>0&&i>0or, even better, by incrementing j separately.

9 Copyright © 2008 W. W. Norton & Company. 11 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements Logical Operators The if Statement • The ! operator has the same precedence as the • Confusing == (equality) with = (assignment) is unary plus and minus operators. perhaps the most common C programming error. • The precedence of && and || is lower than that • The statement of the relational and equality operators. if (i == 0) … – For example, i

12 Copyright © 2008 W. W. Norton & Company. 14 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements The if Statement The if Statement • The if statement allows a program to choose • Often the expression in an if statement will test between two alternatives by testing an expression. whether a variable falls within a range of values. • In its simplest form, the if statement has the form • To test whether 0 i < n: if ( expression ) statement if (0 <= i && i < n) … • When an if statement is executed, expression is • To test the opposite condition (i is outside the evaluated; if its value is nonzero, statement is range): executed. if (i < 0 || i >= n) … • Example: if (line_num == MAX_LINES) line_num = 0;

13 Copyright © 2008 W. W. Norton & Company. 15 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements Compound Statements Compound Statements • In the if statement template, notice that statement • Example of a compound statement used inside an is singular, not plural: if statement: if ( expression ) statement if (line_num == MAX_LINES) { • To make an if statement control two or more line_num = 0; page_num++; statements, use a compound statement. } • A compound statement has the form • Compound statements are also common in loops { statements } and other places where the syntax of C requires a • Putting braces around a group of statements forces single statement. the compiler to treat it as a single statement.

16 Copyright © 2008 W. W. Norton & Company. 18 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements Compound Statements The else Clause • Example: • An if statement may have an else clause: { line_num = 0; page_num++; } if ( expression ) statement else statement • A compound statement is usually put on multiple • The statement that follows the word else is lines, with one statement per line: executed if the expression has the value 0. { • Example: line_num = 0; if (i > j) page_num++; = i; } else • Each inner statement still ends with a semicolon, max = j; but the compound statement itself does not.

17 Copyright © 2008 W. W. Norton & Company. 19 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements The else Clause The else Clause • When an if statement contains an else clause, • To avoid confusion, don’t hesitate to add braces: where should the else be placed? if (i > j) { • Many C programmers align it with the if at the if (i > k) beginning of the statement. max = i; else • Inner statements are usually indented, but if max = k; they’re short they can be put on the same line as } else { the if and else: if (j > k) if (i > j) max = i; max = j; else max = j; else max = k; }

20 Copyright © 2008 W. W. Norton & Company. 22 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements The else Clause The else Clause • It’s not unusual for if statements to be nested inside • Some programmers use as many braces as possible other if statements: inside if statements: if (i > j) if (i > j) { if (i > k) if (i > k) { max = i; max = i; else } else { max = k; max = k; else } if (j > k) } else { max = j; if (j > k) { else max = j; max = k; } else { max = k; • Aligning each else with the matching if makes the } nesting easier to see. }

21 Copyright © 2008 W. W. Norton & Company. 23 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements The else Clause Cascaded if Statements • Advantages of using braces even when they’re not • Although the second if statement is nested inside required: the first, C programmers don’t usually indent it. – Makes programs easier to modify, because more • Instead, they align each else with the original statements can easily be added to any if or else if: clause. if (n < 0) – Helps avoid errors that can result from forgetting to use printf("n is less than 0\n"); if else braces when adding statements to an or else if (n == 0) clause. printf("n is equal to 0\n"); else printf("n is greater than 0\n");

24 Copyright © 2008 W. W. Norton & Company. 26 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements Cascaded if Statements Cascaded if Statements • A “cascaded” if statement is often the best way • This layout avoids the problem of excessive to test a series of conditions, stopping as soon as indentation when the number of tests is large: one of them is true. if ( expression ) • Example: statement else if ( expression ) if (n < 0) statement printf("n is less than 0\n"); … else else if ( expression ) if (n == 0) statement printf("n is equal to 0\n"); else else statement printf("n is greater than 0\n");

25 Copyright © 2008 W. W. Norton & Company. 27 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements

Program: Calculating a Broker’s Commission broker.c /* Calculates a broker's commission */ • When stocks are sold or purchased through a broker, the #include

broker’s commission often depends upon the value of the int main(void) stocks traded. { float commission, value; • Suppose that a broker charges the amounts shown in the printf("Enter value of trade: "); following table: scanf("%f", &value); Transaction size Commission rate if (value < 2500.00f) commission = 30.00f + .017f * value; Under $2,500 $30 + 1.7% else if (value < 6250.00f) $2,500–$6,250 $56 + 0.66% commission = 56.00f + .0066f * value; else if (value < 20000.00f) $6,250–$20,000 $76 + 0.34% commission = 76.00f + .0034f * value; $20,000–$50,000 $100 + 0.22% else if (value < 50000.00f) commission = 100.00f + .0022f * value; $50,000–$500,000 $155 + 0.11% else if (value < 500000.00f) Over $500,000 $255 + 0.09% commission = 155.00f + .0011f * value; else • The minimum charge is $39. commission = 255.00f + .0009f * value;

28 Copyright © 2008 W. W. Norton & Company. 30 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements

if (commission < 39.00f) Program: Calculating a Broker’s Commission commission = 39.00f; printf("Commission: $%.2f\n", commission); • The broker.c program asks the user to enter the return 0; amount of the trade, then displays the amount of } the commission: Enter value of trade: 30000 Commission: $166.00 • The heart of the program is a cascaded if statement that determines which range the trade falls into.

29 Copyright © 2008 W. W. Norton & Company. 31 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements The “Dangling else” Problem The “Dangling else” Problem • When if statements are nested, the “dangling else” • To make the else clause part of the outer if problem may occur: statement, we can enclose the inner if statement if (y != 0) in braces: if (x != 0) result = x / y; if (y != 0) { else if (x != 0) printf("Error: y is equal to 0\n"); result = x / y; • The indentation suggests that the else clause belongs } else to the outer if statement. printf("Error: y is equal to 0\n"); • However, C follows the rule that an else clause • Using braces in the original if statement would belongs to the nearest if statement that hasn’t already have avoided the problem in the first place. been paired with an else.

32 Copyright © 2008 W. W. Norton & Company. 34 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements The “Dangling else” Problem Conditional Expressions • A correctly indented version would look like this: • C’s conditional operator allows an expression to if (y != 0) produce one of two values depending on the value if (x != 0) of a condition. result = x / y; • The conditional operator consists of two symbols else printf("Error: y is equal to 0\n"); (? and :), which must be used together: expr1 ? expr2 : expr3 • The operands can be of any type. • The resulting expression is said to be a conditional expression.

33 Copyright © 2008 W. W. Norton & Company. 35 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements Conditional Expressions Conditional Expressions • The conditional operator requires three operands, • Conditional expressions tend to make programs so it is often referred to as a ternary operator. shorter but harder to understand, so it’s probably • The conditional expression expr1 ? expr2 : expr3 best to use them sparingly. should be read “if expr1 then expr2 else expr3.” • Conditional expressions are often used in return • The expression is evaluated in stages: expr1 is statements: evaluated first; if its value isn’t zero, then expr2 is return i > j ? i : j; evaluated, and its value is the value of the entire conditional expression. • If the value of expr1 is zero, then the value of expr3 is the value of the conditional.

36 Copyright © 2008 W. W. Norton & Company. 38 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements Conditional Expressions Conditional Expressions • Example: • Calls of printf can sometimes benefit from int i, j, k; condition expressions. Instead of

i = 1; if (i > j) j = 2; printf("%d\n", i); k = i > j ? i : j; /* k is now 2 */ else k = (i >= 0 ? i : 0) + j; /* k is now 3 */ printf("%d\n", j); • The parentheses are necessary, because the we could simply write precedence of the conditional operator is less than printf("%d\n", i > j ? i : j); that of the other operators discussed so far, with • Conditional expressions are also common in the exception of the assignment operators. certain kinds of macro definitions.

37 Copyright © 2008 W. W. Norton & Company. 39 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements Boolean Values in C89 Boolean Values in C89 • For many years, the C language lacked a proper • To test whether flag is true, we can write Boolean type, and there is none defined in the C89 if (flag == TRUE) … standard. or just • One way to work around this limitation is to declare if (flag) … an int variable and then assign it either 0 or 1: int flag; • The latter form is more concise. It also works correctly if flag has a value other than 0 or 1. flag = 0; … • To test whether flag is false, we can write flag = 1; if (flag == FALSE) … • Although this scheme works, it doesn’t contribute or much to program readability. if (!flag) …

40 Copyright © 2008 W. W. Norton & Company. 42 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements Boolean Values in C89 Boolean Values in C89 • To make programs more understandable, C89 • Carrying this idea one step further, we might even programmers often define macros with names define a macro that can be used as a type: such as TRUE and FALSE: #define BOOL int #define TRUE 1 • BOOL can take the place of int when declaring #define FALSE 0 Boolean variables: • Assignments to flag now have a more natural BOOL flag; appearance: • It’s now clear that flag isn’t an ordinary integer flag = FALSE; variable, but instead represents a Boolean … condition. flag = TRUE;

41 Copyright © 2008 W. W. Norton & Company. 43 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements Boolean Values in C99 Boolean Values in C99 • C99 provides the _Bool type. • C99’s header makes it easier to work • A Boolean variable can be declared by writing with Boolean values. _Bool flag; • It defines a macro, bool, that stands for _Bool. • _Bool is an integer type, so a _Bool variable is • If is included, we can write really just an integer variable in disguise. bool flag; /* same as _Bool flag; */ • also supplies macros named true • Unlike an ordinary integer variable, however, a and false, which stand for 1 and 0, respectively, _Bool variable can only be assigned 0 or 1. making it possible to write • Attempting to store a nonzero value into a _Bool flag = false; variable will cause the variable to be assigned 1: … flag = 5; /* flag is assigned 1 */ flag = true;

44 Copyright © 2008 W. W. Norton & Company. 46 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements Boolean Values in C99 The switch Statement • It’s legal (although not advisable) to perform • A cascaded if statement can be used to compare an arithmetic on _Bool variables. expression against a series of values: if (grade == 4) • It’s also legal to print a _Bool variable (either 0 printf("Excellent"); or 1 will be displayed). else if (grade == 3) • And, of course, a _Bool variable can be tested in printf("Good"); else if (grade == 2) an if statement: printf("Average"); if (flag) /* tests whether flag is 1 */ else if (grade == 1) … printf("Poor"); else if (grade == 0) printf("Failing"); else printf("Illegal grade");

45 Copyright © 2008 W. W. Norton & Company. 47 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements The switch Statement The switch Statement • The switch statement is an alternative: • The word switch must be followed by an integer switch (grade) { expression—the controlling expression—in case 4: printf("Excellent"); break; parentheses. case 3: printf("Good"); • Characters are treated as integers in C and thus can break; case 2: printf("Average"); be tested in switch statements. break; • Floating-point numbers and strings don’t qualify, case 1: printf("Poor"); break; however. case 0: printf("Failing"); break; default: printf("Illegal grade"); break; }

48 Copyright © 2008 W. W. Norton & Company. 50 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements The switch Statement The switch Statement • A switch statement may be easier to read than a • Each case begins with a label of the form cascaded if statement. case constant-expression : • switch statements are often faster than if • A constant expression is much like an ordinary statements. expression except that it can’t contain variables or • Most common form of the switch statement: function calls. switch ( expression ) { –5is a constant expression, and 5+10is a constant case constant-expression : statements expression, but n+10isn’t a constant expression … (unless n is a macro that represents a constant). case constant-expression : statements • The constant expression in a case label must default : statements evaluate to an integer (characters are acceptable). }

49 Copyright © 2008 W. W. Norton & Company. 51 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements The switch Statement The switch Statement • After each case label comes any number of • To save space, several case labels can be put on the statements. same line: switch (grade) { • No braces are required around the statements. case 4: case 3: case 2: case 1: • The last statement in each group is normally printf("Passing"); break; break. case 0: printf("Failing"); break; default: printf("Illegal grade"); break; } • If the default case is missing and the controlling expression’s value doesn’t match any case label, control passes to the next statement after the switch.

52 Copyright © 2008 W. W. Norton & Company. 54 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements The switch Statement The Role of the break Statement • Duplicate case labels aren’t allowed. • Executing a break statement causes the program • The order of the cases doesn’t matter, and the default to “break” out of the switch statement; execution case doesn’t need to come last. continues at the next statement after the switch. • Several case labels may precede a group of statements: • The switch statement is really a form of switch (grade) { case 4: “computed jump.” case 3: case 2: • When the controlling expression is evaluated, case 1: printf("Passing"); control jumps to the case label matching the value break; case 0: printf("Failing"); of the switch expression. break; default: printf("Illegal grade"); • A case label is nothing more than a marker break; indicating a position within the switch. }

53 Copyright © 2008 W. W. Norton & Company. 55 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 5: Selection Statements The Role of the break Statement Program: Printing a Date in Legal Form • Without break (or some other jump statement) at the • Contracts and other legal documents are often dated in end of a case, control will flow into the next case. the following way: • Example: Dated this ______day of ______, 20__ . switch (grade) { • The date.c program will display a date in this form case 4: printf("Excellent"); after the user enters the date in month/day/year form: case 3: printf("Good"); case 2: printf("Average"); Enter date (mm//yy): 7/19/14 case 1: printf("Poor"); Dated this 19th day of July, 2014. case 0: printf("Failing"); • The program uses switch statements to add “th” (or default: printf("Illegal grade"); “st” or “nd” or “rd”) to the day, and to print the month } as a word instead of a number. • If the value of grade is 3, the message printed is GoodAveragePoorFailingIllegal grade

56 Copyright © 2008 W. W. Norton & Company. 58 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 5: Selection Statements Chapter 5: Selection Statements The Role of the break Statement date.c /* Prints a date in legal form */ • Omitting break is sometimes done intentionally, but #include it’s usually just an oversight. int main(void) { • It’s a good idea to point out deliberate omissions of int month, day, year; break : printf("Enter date (mm/dd/yy): "); switch (grade) { scanf("%d /%d /%d", &month, &day, &year); case 4: case 3: case 2: case 1: printf("Dated this %d", day); num_passing++; switch (day) { /* FALL THROUGH */ case 1: case 21: case 31: printf("st"); break; case 0: total_grades++; case 2: case 22: break; printf("nd"); break; } case 3: case 23: printf("rd"); break; • Although the last case never needs a break statement, default: printf("th"); break; } including one makes it easy to add cases in the future. printf(" day of ");

57 Copyright © 2008 W. W. Norton & Company. 59 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 5: Selection Statements Chapter 6: Loops

switch (month) { case 1: printf("January"); break; Iteration Statements case 2: printf("February"); break; case 3: printf("March"); break; case 4: printf("April"); break; • C’s iteration statements are used to set up loops. case 5: printf("May"); break; case 6: printf("June"); break; • A loop is a statement whose job is to repeatedly case 7: printf("July"); break; case 8: printf("August"); break; execute some other statement (the loop body). case 9: printf("September"); break; case 10: printf("October"); break; • In C, every loop has a controlling expression. case 11: printf("November"); break; case 12: printf("December"); break; } • Each time the loop body is executed (an iteration printf(", 20%.2d.\n", year); of the loop), the controlling expression is return 0; } evaluated. – If the expression is true (has a value that’s not zero) the loop continues to execute.

60 Copyright © 2008 W. W. Norton & Company. 2 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops Iteration Statements • C provides three iteration statements: – The while statement is used for loops whose controlling expression is tested before the loop body is Chapter 6 executed. – The do statement is used if the expression is tested Loops after the loop body is executed. – The for statement is convenient for loops that increment or decrement a counting variable.

1 Copyright © 2008 W. W. Norton & Company. 3 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops The while Statement The while Statement • Using a while statement is the easiest way to set • A while statement that computes the smallest power of up a loop. 2 that is greater than or equal to a number n: i = 1; • The while statement has the form while (i < n) i = i * 2; while ( expression ) statement • A trace of the loop when n has the value 10: • expression is the controlling expression; statement i = 1; i is now 1. Is i

4 Copyright © 2008 W. W. Norton & Company. 6 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops The while Statement The while Statement • Example of a while statement: • Although the loop body must be a single statement, while (i < n) /* controlling expression */ that’s merely a technicality. i = i * 2; /* loop body */ • If multiple statements are needed, use braces to create • When a while statement is executed, the a single compound statement: controlling expression is evaluated first. while (i > 0) { printf("T minus %d and counting\n", i); • If its value is nonzero (true), the loop body is i--; executed and the expression is tested again. } • Some programmers always use braces, even when • The process continues until the controlling they’re not strictly necessary: expression eventually has the value zero. while (i < n) { i = i * 2; }

5 Copyright © 2008 W. W. Norton & Company. 7 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops The while Statement Infinite Loops • The following statements display a series of • A while statement won’t terminate if the controlling “countdown” messages: expression always has a nonzero value. i = 10; • C programmers sometimes deliberately create an while (i > 0) { infinite loop by using a nonzero constant as the printf("T minus %d and counting\n", i); controlling expression: i--; while (1) … } • A while statement of this form will execute forever • The final message printed is T minus 1 and unless its body contains a statement that transfers counting. control out of the loop (break, goto, return) or calls a function that causes the program to terminate.

8 Copyright © 2008 W. W. Norton & Company. 10 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops The while Statement Program: Printing a Table of Squares • Observations about the while statement: • The square.c program uses a while statement – The controlling expression is false when a while loop to print a table of squares. terminates. Thus, when a loop controlled by i>0 • The user specifies the number of entries in the terminates, i must be less than or equal to 0. table: – The body of a while loop may not be executed at all, This program prints a table of squares. because the controlling expression is tested before the Enter number of entries in table: 5 body is executed. 1 1 – A while statement can often be written in a variety of 2 4 ways. A more concise version of the countdown loop: 3 9 while (i > 0) 4 16 printf("T minus %d and counting\n", i--); 5 25

9 Copyright © 2008 W. W. Norton & Company. 11 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops square.c sum.c /* Prints a table of squares using a while statement */ /* Sums a series of numbers */

#include #include int main(void) int main(void) { { int i, n; int n, sum = 0;

printf("This program prints a table of squares.\n"); printf("This program sums a series of integers.\n"); printf("Enter number of entries in table: "); printf("Enter integers (0 to terminate): "); scanf("%d", &n); scanf("%d", &n); i = 1; while (n != 0) { while (i <= n) { sum += n; printf("%10d%10d\n", i, i * i); scanf("%d", &n); i++; } } printf("The sum is: %d\n", sum);

return 0; return 0; } }

12 Copyright © 2008 W. W. Norton & Company. 14 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops Program: Summing a Series of Numbers The do Statement • The sum.c program sums a series of integers • General form of the do statement: entered by the user: do statement while ( expression ) ; This program sums a series of integers. • When a do statement is executed, the loop body is Enter integers (0 to terminate): 8 23 71 5 0 executed first, then the controlling expression is The sum is: 107 evaluated. • The program will need a loop that uses scanf to read a number and then adds the number to a • If the value of the expression is nonzero, the loop running total. body is executed again and then the expression is evaluated once more.

13 Copyright © 2008 W. W. Norton & Company. 15 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops Program: Calculating the The do Statement Number of Digits in an Integer • The countdown example rewritten as a do • The numdigits.c program calculates the statement: number of digits in an integer entered by the user: i = 10; Enter a nonnegative integer: 60 do { The number has 2 digit(s). printf("T minus %d and counting\n", i); --i; • The program will divide the user’s input by 10 } while (i > 0); repeatedly until it becomes 0; the number of • The do statement is often indistinguishable from the divisions performed is the number of digits. while statement. • Writing this loop as a do statement is better than • The only difference is that the body of a do using a while statement, because every integer— statement is always executed at least once. even 0—has at least one digit.

16 Copyright © 2008 W. W. Norton & Company. 18 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops The do Statement numdigits.c /* Calculates the number of digits in an integer */ • It’s a good idea to use braces in all do statements, #include whether or not they’re needed, because a do int main(void) statement without braces can easily be mistaken { for a while statement: int digits = 0, n; do printf("Enter a nonnegative integer: "); scanf("%d", &n); printf("T minus %d and counting\n", i--); while (i > 0); do { n /= 10; • A careless reader might think that the word digits++; } while (n > 0); while was the beginning of a while statement. printf("The number has %d digit(s).\n", digits);

return 0; }

17 Copyright © 2008 W. W. Norton & Company. 19 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops The for Statement The for Statement • The for statement is ideal for loops that have a • expr2 controls loop termination (the loop continues “counting” variable, but it’s versatile enough to be executing as long as the value of expr2 is nonzero). used for other kinds of loops as well. • expr3 is an operation to be performed at the end of • General form of the for statement: each loop iteration. for ( expr1 ; expr2 ; expr3 ) statement • The result when this pattern is applied to the previous for loop: expr1, expr2, and expr3 are expressions. i = 10; • Example: while (i > 0) { for (i = 10; i > 0; i--) printf("T minus %d and counting\n", i); printf("T minus %d and counting\n", i); i--; }

20 Copyright © 2008 W. W. Norton & Company. 22 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops The for Statement The for Statement • The for statement is closely related to the while • Studying the equivalent while statement can statement. help clarify the fine points of a for statement. • Except in a few rare cases, a for loop can always be • For example, what if i-- is replaced by --i? replaced by an equivalent while loop: for (i = 10; i > 0; --i) expr1; printf("T minus %d and counting\n", i); while ( expr2 ) { • The equivalent while loop shows that the change statement expr3; has no effect on the behavior of the loop: } i = 10; while (i > 0) { • expr1 is an initialization step that’s performed only printf("T minus %d and counting\n", i); once, before the loop begins to execute. --i; }

21 Copyright © 2008 W. W. Norton & Company. 23 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops The for Statement for Statement Idioms • Since the first and third expressions in a for • Common for statement errors: statement are executed as statements, their values – Using < instead of > (or vice versa) in the controlling are irrelevant—they’re useful only for their side expression. “Counting up” loops should use the < or <= effects. operator. “Counting down” loops should use > or >=. == < <= • Consequently, these two expressions are usually – Using in the controlling expression instead of , , >, or >=. assignments or increment/decrement expressions. – “Off-by-one” errors such as writing the controlling expression as i<=ninstead of i

24 Copyright © 2008 W. W. Norton & Company. 26 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops for Statement Idioms Omitting Expressions in a for Statement • The for statement is usually the best choice for • C allows any or all of the expressions that control a loops that “count up” (increment a variable) or “count for statement to be omitted. down” (decrement a variable). • If the first expression is omitted, no initialization is • A for statement that counts up or down a total of n performed before the loop is executed: i = 10; times will usually have one of the following forms: for (; i > 0; --i) Counting up from 0 to n–1: for (i = 0; i < n; i++) … printf("T minus %d and counting\n", i); Counting up from 1 to n: for (i = 1; i <= n; i++) … • If the third expression is omitted, the loop body is responsible for ensuring that the value of the second Counting down from n–1 to 0: for (i = n - 1; i >= 0; i--) … expression eventually becomes false: Counting down from n to 1: for (i = n; i > 0; i--) … for (i = 10; i > 0;) printf("T minus %d and counting\n", i--);

25 Copyright © 2008 W. W. Norton & Company. 27 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops Omitting Expressions in a for Statement for Statements in C99 • When the first and third expressions are both • In C99, the first expression in a for statement can omitted, the resulting loop is nothing more than a be replaced by a declaration. while statement in disguise: • This feature allows the programmer to declare a for (; i > 0;) variable for use by the loop: printf("T minus %d and counting\n", i--); for (int i = 0; i < n; i++) is the same as … while (i > 0) • The variable i need not have been declared prior printf("T minus %d and counting\n", i--); to this statement. • The while version is clearer and therefore preferable.

28 Copyright © 2008 W. W. Norton & Company. 30 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops Omitting Expressions in a for Statement for Statements in C99 • If the second expression is missing, it defaults to a • A variable declared by a for statement can’t be true value, so the for statement doesn’t terminate accessed outside the body of the loop (we say that (unless stopped in some other fashion). it’s not visible outside the loop): • For example, some programmers use the for (int i = 0; i < n; i++) { following for statement to establish an infinite … loop: printf("%d", i); /* legal; i is visible inside loop */ for (;;) … … } printf("%d", i); /*** WRONG ***/

29 Copyright © 2008 W. W. Norton & Company. 31 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops for Statements in C99 The Comma Operator • Having a for statement declare its own control • A comma expression is evaluated in two steps: variable is usually a good idea: it’s convenient and – First, expr1 is evaluated and its value discarded. it can make programs easier to understand. – Second, expr2 is evaluated; its value is the value of the entire expression. • However, if the program needs to access the • Evaluating expr1 should always have a side effect; if variable after loop termination, it’s necessary to it doesn’t, then expr1 serves no purpose. use the older form of the for statement. • When the comma expression ++i, i + j is • A for statement may declare more than one evaluated, i is first incremented, then i+jis variable, provided that all variables have the same evaluated. type: – If i and j have the values 1 and 5, respectively, the value of for (int i = 0, j = 0; i < n; i++) the expression will be 7, and i will be incremented to 2. …

32 Copyright © 2008 W. W. Norton & Company. 34 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops The Comma Operator The Comma Operator • On occasion, a for statement may need to have • The comma operator is left associative, so the two (or more) initialization expressions or one that compiler interprets increments several variables each time through the i = 1, j = 2, k = i + j loop. as • This effect can be accomplished by using a ((i = 1), (j = 2)), (k = (i + j)) comma expression as the first or third expression • Since the left operand in a comma expression is in the for statement. evaluated before the right operand, the • A comma expression has the form assignments i=1,j=2, and k=i+jwill be expr1 , expr2 performed from left to right. where expr1 and expr2 are any two expressions.

33 Copyright © 2008 W. W. Norton & Company. 35 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops The Comma Operator square2.c /* Prints a table of squares using a for statement */ • The comma operator makes it possible to “glue” two expressions together to form a single expression. #include int main(void) • Certain macro definitions can benefit from the comma { operator. int i, n;

• The for statement is the only other place where the printf("This program prints a table of squares.\n"); comma operator is likely to be found. printf("Enter number of entries in table: "); scanf("%d", &n); • Example: for (i = 1; i <= n; i++) for (sum = 0, i = 1; i <= N; i++) printf("%10d%10d\n", i, i * i); sum += i; return 0; • With additional commas, the for statement could } initialize more than two variables.

36 Copyright © 2008 W. W. Norton & Company. 38 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops Program: Printing a Table Program: Printing a Table of Squares (Revisited) of Squares (Revisited) • The square.c program (Section 6.1) can be • C places no restrictions on the three expressions that improved by converting its while loop to a for control the behavior of a for statement. loop. • Although these expressions usually initialize, test, and update the same variable, there’s no requirement that they be related in any way. • The square3.c program is equivalent to square2.c, but contains a for statement that initializes one variable (square), tests another (i), and increments a third (odd). • The flexibility of the for statement can sometimes be useful, but in this case the original program was clearer.

37 Copyright © 2008 W. W. Norton & Company. 39 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops square3.c The break Statement /* Prints a table of squares using an odd method */

#include • The break statement can transfer control out of a int main(void) switch statement, but it can also be used to jump { int i, n, odd, square; out of a while, do, or for loop. printf("This program prints a table of squares.\n"); • A loop that checks whether a number n is prime printf("Enter number of entries in table: "); scanf("%d", &n); can use a break statement to terminate the loop

i = 1; as soon as a divisor is found: odd = 3; for (square = 1; i <= n; odd += 2) { for (d = 2; d < n; d++) printf("%10d%10d\n", i, square); if (n % d == 0) ++i; square += odd; break; }

return 0; }

40 Copyright © 2008 W. W. Norton & Company. 42 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops Exiting from a Loop The break Statement • The normal point for a loop is at the • After the loop has terminated, an if statement can beginning (as in a while or for statement) or at be use to determine whether termination was the end (the do statement). premature (hence n isn’t prime) or normal (n is • Using the break statement, it’s possible to write prime): a loop with an exit point in the middle or a loop if (d < n) with more than one exit point. printf("%d is divisible by %d\n", n, d); else printf("%d is prime\n", n);

41 Copyright © 2008 W. W. Norton & Company. 43 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops The break Statement The continue Statement • The break statement is particularly useful for writing • The continue statement is similar to break: loops in which the exit point is in the middle of the body – break transfers control just past the end of a loop. rather than at the beginning or end. – continue transfers control to a point just before the • Loops that read user input, terminating when a particular end of the loop body. value is entered, often fall into this category: • With break, control leaves the loop; with for (;;) { printf("Enter a number (enter 0 to stop): "); continue, control remains inside the loop. scanf("%d", &n); • There’s another difference between break and if (n == 0) continue break switch break; : can be used in printf("%d cubed is %d\n", n, n * n * n); statements and loops (while, do, and for), } whereas continue is limited to loops.

44 Copyright © 2008 W. W. Norton & Company. 46 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops The break Statement The continue Statement • A break statement transfers control out of the innermost • A loop that uses the continue statement: enclosing while, do, for, or switch. n = 0; • When these statements are nested, the break statement sum = 0; can escape only one level of nesting. while (n < 10) { • Example: scanf("%d", &i); while (…) { if (i == 0) switch (…) { continue; … break; sum += i; … n++; } } /* continue jumps to here */ • break transfers control out of the switch statement, but } not out of the while loop.

45 Copyright © 2008 W. W. Norton & Company. 47 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops The continue Statement The goto Statement • The same loop written without using continue: • If C didn’t have a break statement, a goto n = 0; statement could be used to exit from a loop: sum = 0; for (d = 2; d < n; d++) while (n < 10) { if (n % d == 0) scanf("%d", &i); goto done; if (i != 0) { done: sum += i; if (d < n) n++; printf("%d is divisible by %d\n", n, d); } else } printf("%d is prime\n", n);

48 Copyright © 2008 W. W. Norton & Company. 50 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops The goto Statement The goto Statement • The goto statement is capable of jumping to any • The goto statement is rarely needed in everyday statement in a function, provided that the statement has a C programming. label. • The break, continue, and return • A label is just an identifier placed at the beginning of a statement: statements—which are essentially restricted goto identifier : statement statements—and the exit function are sufficient • A statement may have more than one label. to handle most situations that might require a • The goto statement itself has the form goto in other languages. goto identifier ; • Nonetheless, the goto statement can be helpful • Executing the statement goto L; transfers control to the once in a while. statement that follows the label L, which must be in the same function as the goto statement itself.

49 Copyright © 2008 W. W. Norton & Company. 51 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops The goto Statement Program: Balancing a Checkbook • Consider the problem of exiting a loop from within a • Executing the command will require a switch switch statement. statement (or cascaded if statement): • The break statement doesn’t have the desired effect: it exits for (;;) { from the switch, but not from the loop. prompt user to enter command; • A goto statement solves the problem: read command; while (…) { switch (command) { switch (…) { case command : perform operation ; break; … 1 1 case command : perform operation ; break; goto loop_done; /* break won't work here */ . 2 2 … . } . } case command : perform operation ; break; loop_done: … n n default: print error message; break; • The goto statement is also useful for exiting from nested } loops. }

52 Copyright © 2008 W. W. Norton & Company. 54 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops Program: Balancing a Checkbook Program: Balancing a Checkbook • Many simple interactive programs present the user with a • The checking.c program, which maintains a list of commands to choose from. checkbook balance, uses a loop of this type. • Once a command is entered, the program performs the • The user is allowed to clear the account balance, desired action, then prompts the user for another command. credit money to the account, debit money from the • This process continues until the user selects an “exit” or account, display the current balance, and exit the “quit” command. program. • The heart of such a program will be a loop: for (;;) { prompt user to enter command; read command; execute command; }

53 Copyright © 2008 W. W. Norton & Company. 55 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops

case 1: Program: Balancing a Checkbook printf("Enter amount of credit: "); scanf("%f", &credit); *** ACME checkbook-balancing program *** balance += credit; Commands: 0=clear, 1=credit, 2=debit, 3=balance, 4=exit break; case 2: Enter command: 1 printf("Enter amount of debit: "); Enter amount of credit: 1042.56 scanf("%f", &debit); Enter command: 2 balance -= debit; Enter amount of debit: 133.79 break; Enter command: 1 case 3: Enter amount of credit: 1754.32 printf("Current balance: $%.2f\n", balance); Enter command: 2 break; Enter amount of debit: 1400 case 4: Enter command: 2 return 0; Enter amount of debit: 68 default: Enter command: 2 printf("Commands: 0=clear, 1=credit, 2=debit, "); Enter amount of debit: 50 printf("3=balance, 4=exit\n\n"); Enter command: 3 break; Current balance: $1145.09 } Enter command: 4 } }

56 Copyright © 2008 W. W. Norton & Company. 58 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 6: Loops checking.c The Null Statement /* Balances a checkbook */

#include • A statement can be null—devoid of symbols except for the semicolon at the end. int main(void) { • The following line contains three statements: int cmd; float balance = 0.0f, credit, debit; i = 0; ; j = 1; printf("*** ACME checkbook-balancing program ***\n"); • The null statement is primarily good for one thing: printf("Commands: 0=clear, 1=credit, 2=debit, "); printf("3=balance, 4=exit\n\n"); writing loops whose bodies are empty. for (;;) { printf("Enter command: "); scanf("%d", &cmd); switch (cmd) { case 0: balance = 0.0f; break;

57 Copyright © 2008 W. W. Norton & Company. 59 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 6: Loops Chapter 6: Loops The Null Statement The Null Statement • Consider the following prime-finding loop: • Example 3: for (d = 2; d < n; d++) i = 11; if (n % d == 0) while (--i > 0); /*** WRONG ***/ printf("T minus %d and counting\n", i); break; The loop body is executed only once; the message printed • If the n%d==0condition is moved into the is: loop’s controlling expression, the body of the loop T minus 0 and counting becomes empty: • Example 4: for (d = 2; d < n && n % d != 0; d++) for (i = 10; i > 0; i--); /*** WRONG ***/ /* empty loop body */ ; printf("T minus %d and counting\n", i); • To avoid confusion, C programmers customarily Again, the loop body is executed only once, and the same put the null statement on a line by itself. message is printed as in Example 3.

60 Copyright © 2008 W. W. Norton & Company. 62 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 6: Loops Chapter 7: Basic Types The Null Statement • Accidentally putting a semicolon after the parentheses in an if, while, or for statement creates a null statement. • Example 1: if (d == 0); /*** WRONG ***/ printf("Error: Division by zero\n"); Chapter 7 The call of printf isn’t inside the if statement, so it’s performed regardless of whether d is equal to 0. Basic Types • Example 2: i = 10; while (i > 0); /*** WRONG ***/ { printf("T minus %d and counting\n", i); --i; } The extra semicolon creates an infinite loop.

61 Copyright © 2008 W. W. Norton & Company. 1 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Basic Types Signed and Unsigned Integers • C’s basic (built-in) types: • The leftmost bit of a signed integer (known as the sign bit) is – Integer types, including long integers, short integers, 0 if the number is positive or zero, 1 if it’s negative. and unsigned integers • The largest 16-bit integer has the binary representation 15 – Floating types (float, double, and long double) 0111111111111111, which has the value 32,767 (2 – 1). – char • The largest 32-bit integer is – _Bool (C99) 01111111111111111111111111111111 which has the value 2,147,483,647 (231 – 1). • An integer with no sign bit (the leftmost bit is considered part of the number’s magnitude) is said to be unsigned. • The largest 16-bit unsigned integer is 65,535 (216 – 1). • The largest 32-bit unsigned integer is 4,294,967,295 (232 – 1).

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Integer Types Signed and Unsigned Integers • C supports two fundamentally different kinds of • By default, integer variables are signed in C—the numeric types: integer types and floating types. leftmost bit is reserved for the sign. • Values of an integer type are whole numbers. • To tell the compiler that a variable has no sign bit, • Values of a floating type can have a fractional part declare it to be unsigned. as well. • Unsigned numbers are primarily useful for • The integer types, in turn, are divided into two systems programming and low-level, machine- categories: signed and unsigned. dependent applications.

3 Copyright © 2008 W. W. Norton & Company. 5 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Integer Types Integer Types • The int type is usually 32 bits, but may be 16 bits on older • Typical ranges of values for the integer types on a CPUs. 16-bit machine: • Long integers may have more bits than ordinary integers; Type Smallest Value Largest Value short integers may have fewer bits. short int –32,768 32,767 • The specifiers long and short, as well as signed and unsigned short int 065,535 unsigned, can be combined with int to form integer types. int –32,768 32,767 • Only six combinations produce different types: unsigned int 065,535 short int unsigned short int long int –2,147,483,648 2,147,483,647 int unsigned int unsigned long int 0 4,294,967,295 long int unsigned long int • The order of the specifiers doesn’t matter. Also, the word int can be dropped (long int can be abbreviated to just long).

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Integer Types Integer Types • The range of values represented by each of the six • Typical ranges on a 32-bit machine: integer types varies from one machine to another. Type Smallest Value Largest Value • However, the C standard requires that short short int –32,768 32,767 int int long int unsigned short int 065,535 , , and must each cover a int –2,147,483,648 2,147,483,647 certain minimum range of values. unsigned int 0 4,294,967,295 • Also, int must not be shorter than short int, long int –2,147,483,648 2,147,483,647 and long int must not be shorter than int. unsigned long int 0 4,294,967,295

7 Copyright © 2008 W. W. Norton & Company. 9 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Integer Types Integer Types in C99 • Typical ranges on a 64-bit machine: • The short int, int, long int, and long long Type Smallest Value Largest Value int types (along with the signed char type) are short int –32,768 32,767 called standard signed integer types in C99. unsigned short int 065,535 • The unsigned short int, unsigned int, int –2,147,483,648 2,147,483,647 unsigned long int, and unsigned long long unsigned int 0 4,294,967,295 int types (along with the unsigned char type and long int –263 263–1 unsigned long int 0264–1 the _Bool type) are called standard unsigned integer • The header defines macros that types. represent the smallest and largest values of each • In addition to the standard integer types, the C99 integer type. standard allows implementation-defined extended integer types, both signed and unsigned.

10 Copyright © 2008 W. W. Norton & Company. 12 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Integer Types in C99 Integer Constants • C99 provides two additional standard integer types, • Constants are numbers that appear in the text of a long long int and unsigned long long int. program. • Both long long types are required to be at least 64 • C allows integer constants to be written in decimal bits wide. (base 10), octal (base 8), or (base • The range of long long int values is typically –263 16). (–9,223,372,036,854,775,808) to 263 – 1 (9,223,372,036,854,775,807). • The range of unsigned long long int values is usually 0 to 264 – 1 (18,446,744,073,709,551,615).

11 Copyright © 2008 W. W. Norton & Company. 13 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Octal and Hexadecimal Numbers Integer Constants • Octal numbers use only the digits 0 through 7. • The type of a decimal integer constant is normally int. • Each position in an octal number represents a • If the value of the constant is too large to store as an power of 8. int, the constant has type long int instead. – The octal number 237 represents the decimal number • If the constant is too large to store as a long int, the 2 × 82 + 3 × 81 + 7 × 80 = 128 + 24 + 7 = 159. compiler will try unsigned long int as a last • A hexadecimal (or hex) number is written using resort. the digits 0 through 9 plus the letters A through F, • For an octal or hexadecimal constant, the rules are which stand for 10 through 15, respectively. slightly different: the compiler will go through the types int, unsigned int, long int, and – The hex number 1AF has the decimal value 1 × 162 + unsigned long int until it finds one capable of 10 × 161 + 15 × 160 = 256 + 160 + 15 = 431. representing the constant.

14 Copyright © 2008 W. W. Norton & Company. 16 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Integer Constants Integer Constants • Decimal constants contain digits between 0 and 9, but • To force the compiler to treat a constant as a long must not begin with a zero: integer, just follow it with the letter L (or l): 15 255 32767 15L 0377L 0x7fffL • Octal constants contain only digits between 0 and 7, and must begin with a zero: • To indicate that a constant is unsigned, put the 017 0377 077777 letter U (or u) after it: • Hexadecimal constants contain digits between 0 and 9 and 15U 0377U 0x7fffU letters between a and f, and always begin with 0x: •Land U may be used in combination: 0xf 0xff 0x7fff 0xffffffffUL • The letters in a hexadecimal constant may be either upper or lower case: The order of the L and U doesn’t matter, nor does 0xff 0xfF 0xFf 0xFF 0Xff 0XfF 0XFf 0XFF their case.

15 Copyright © 2008 W. W. Norton & Company. 17 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Integer Constants in C99 Integer Overflow • In C99, integer constants that end with either LL or ll (the • When arithmetic operations are performed on case of the two letters must match) have type long long integers, it’s possible that the result will be too int . large to represent. • Adding the letter U (or u) before or after the LL or ll denotes a constant of type unsigned long long int. • For example, when an arithmetic operation is int • C99’s general rules for determining the type of an integer performed on two values, the result must be constant are a bit different from those in C89. able to be represented as an int. • The type of a decimal constant with no suffix (U, u, L, l, • If the result can’t be represented as an int LL, or ll) is the “smallest” of the types int, long int, (because it requires too many bits), we say that or long long int that can represent the value of that overflow has occurred. constant.

18 Copyright © 2008 W. W. Norton & Company. 20 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Integer Constants in C99 Integer Overflow • For an octal or hexadecimal constant, the list of • The behavior when integer overflow occurs possible types is int, unsigned int, long int, depends on whether the operands were signed or unsigned long int, long long int, and unsigned. unsigned long long int, in that order. – When overflow occurs during an operation on signed • Any suffix at the end of a constant changes the list of integers, the program’s behavior is undefined. possible types. – When overflow occurs during an operation on unsigned – A constant that ends with U (or u) must have one of the integers, the result is defined: we get the correct answer types unsigned int, unsigned long int, or modulo 2n, where n is the number of bits used to store unsigned long long int. the result. – A decimal constant that ends with L (or l) must have one of the types long int or long long int.

19 Copyright © 2008 W. W. Norton & Company. 21 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Program: Summing a Series Reading and Writing Integers of Numbers (Revisited) • Reading and writing unsigned, short, and long integers • The sum.c program (Chapter 6) sums a series of integers. requires new conversion specifiers. • One problem with this program is that the sum (or one of • When reading or writing an unsigned integer, use the the input numbers) might exceed the largest value allowed letter u, o, or x instead of d in the conversion for an int variable. specification. • Here’s what might happen if the program is run on a unsigned int u; machine whose integers are 16 bits long: This program sums a series of integers. scanf("%u", &u); /* reads u in base 10 */ Enter integers (0 to terminate): 10000 20000 30000 0 printf("%u", u); /* writes u in base 10 */ The sum is: -5536 scanf("%o", &u); /* reads u in base 8 */ printf("%o", u); /* writes u in base 8 */ • When overflow occurs with signed numbers, the outcome scanf("%x", &u); /* reads u in base 16 */ is undefined. printf("%x", u); /* writes u in base 16 */ • The program can be improved by using long variables.

22 Copyright © 2008 W. W. Norton & Company. 24 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Reading and Writing Integers sum2.c /* Sums a series of numbers (using long variables) */

• When reading or writing a short integer, put the #include letter h in front of d, o, u, or x: int main(void) short s; { long n, sum = 0; scanf("%hd", &s); printf("This program sums a series of integers.\n"); printf("%hd", s); printf("Enter integers (0 to terminate): "); • When reading or writing a long integer, put the scanf("%ld", &n); while (n != 0) { letter l (“ell,” not “one”) in front of d, o, u, or x. sum += n; scanf("%ld", &n); • When reading or writing a long long integer (C99 } only), put the letters ll in front of d, o, u, or x. printf("The sum is: %ld\n", sum); return 0; }

23 Copyright © 2008 W. W. Norton & Company. 25 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Floating Types The IEEE Floating-Point Standard • C provides three floating types, corresponding to • IEEE Standard 754 was developed by the Institute of different floating-point formats: Electrical and Electronics Engineers. – float Single-precision floating-point • It has two primary formats for floating-point numbers: – double Double-precision floating-point single precision (32 bits) and double precision (64 bits). – long double Extended-precision floating-point • Numbers are stored in a form of , with each number having a sign, an exponent, and a fraction. • In single-precision format, the exponent is 8 bits long, while the fraction occupies 23 bits. The maximum value is approximately 3.40 × 1038, with a precision of about 6 decimal digits.

26 Copyright © 2008 W. W. Norton & Company. 28 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Floating Types Floating Types • float is suitable when the amount of precision isn’t • Characteristics of float and double when critical. implemented according to the IEEE standard: • double provides enough precision for most Type Smallest Positive Value Largest Value Precision programs. float 1.17549 10–38 3.40282 1038 6 digits –308 308 • long double is rarely used. double 2.22507 10 1.79769 10 15 digits • The C standard doesn’t state how much precision the • On computers that don’t follow the IEEE standard, float, double, and long double types provide, this table won’t be valid. since that depends on how numbers are stored. • In fact, on some machines, float may have the • Most modern computers follow the specifications in same set of values as double, or double may IEEE Standard 754 (also known as IEC 60559). have the same values as long double.

27 Copyright © 2008 W. W. Norton & Company. 29 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Floating Types Floating Constants • Macros that define the characteristics of the • By default, floating constants are stored as double- floating types can be found in the precision numbers. header. • To indicate that only single precision is desired, • In C99, the floating types are divided into two put the letter F (or f) at the end of the constant categories. (for example, 57.0F). – Real floating types (float, double, long double) • To indicate that a constant should be stored in – Complex types (float _Complex, double long double format, put the letter L (or l) at _Complex, long double _Complex) the end (57.0L).

30 Copyright © 2008 W. W. Norton & Company. 32 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Reading and Writing Floating Constants Floating-Point Numbers • Floating constants can be written in a variety of ways. • The conversion specifications %e, %f, and %g are used for • Valid ways of writing the number 57.0: reading and writing single-precision floating-point numbers. 57.0 57. 57.0e0 57E0 5.7e1 5.7e+1 • When reading a value of type double, put the letter l in .57e2 570.e-1 front of e, f, or g: double d; • A floating constant must contain a decimal point and/or an exponent; the exponent indicates the power scanf("%lf", &d); of 10 by which the number is to be scaled. • Note: Use l only in a scanf format string, not a printf string. • If an exponent is present, it must be preceded by the • In a printf format string, the e, f, and g conversions can letter E (or e). An optional + or - sign may appear be used to write either float or double values. E e after the (or ). • When reading or writing a value of type long double, put the letter L in front of e, f, or g.

31 Copyright © 2008 W. W. Norton & Company. 33 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Character Types Character Sets • The only remaining basic type is char, the • A variable of type char can be assigned any character type. single character: • The values of type char can vary from one char ch; computer to another, because different machines ch = 'a'; /* lower-case a */ may have different underlying character sets. ch = 'A'; /* upper-case A */ ch = '0'; /* zero */ ch = ' '; /* space */ • Notice that character constants are enclosed in single quotes, not double quotes.

34 Copyright © 2008 W. W. Norton & Company. 36 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Character Sets Operations on Characters • Today’s most popular character set is ASCII • Working with characters in C is simple, because (American Standard Code for Information of one fact: C treats characters as small integers. Interchange), a 7-bit code capable of representing • In ASCII, character codes range from 0000000 to 128 characters. 1111111, which we can think of as the integers • ASCII is often extended to a 256-character code from 0 to 127. known as Latin-1 that provides the characters • The character 'a' has the value 97, 'A' has the necessary for Western European and many value 65, '0' has the value 48, and ' ' has the African languages. value 32. • Character constants actually have int type rather than char type.

35 Copyright © 2008 W. W. Norton & Company. 37 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Operations on Characters Operations on Characters • When a character appears in a computation, C uses • The fact that characters have the same properties as its integer value. numbers has advantages. • Consider the following examples, which assume • For example, it is easy to write a for statement whose the ASCII character set: control variable steps through all the upper-case letters: for (ch = 'A'; ch <= 'Z'; ch++) … char ch; int i; • Disadvantages of treating characters as numbers: – Can lead to errors that won’t be caught by the compiler. i = 'a'; /* i is now 97 */ – Allows meaningless expressions such as'a' * 'b' / 'c'. ch = 65; /* ch is now 'A' */ – Can hamper portability, since programs may rely on ch = ch + 1; /* ch is now 'B' */ assumptions about the underlying character set. ch++; /* ch is now 'C' */

38 Copyright © 2008 W. W. Norton & Company. 40 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Operations on Characters Signed and Unsigned Characters • Characters can be compared, just as numbers can. • The char type—like the integer types—exists in both • An if statement that converts a lower-case letter signed and unsigned versions. to upper case: • Signed characters normally have values between –128 and 127. Unsigned characters have values between 0 if ('a' <= ch && ch <= 'z') and 255. ch = ch - 'a' + 'A'; • Some compilers treat char as a signed type, while 'a' <= ch • Comparisons such as are done using others treat it as an unsigned type. Most of the time, it the integer values of the characters involved. doesn’t matter. • These values depend on the character set in use, so • C allows the use of the words signed and unsigned programs that use <, <=, >, and >= to compare to modify char: characters may not be portable. signed char sch; unsigned char uch;

39 Copyright © 2008 W. W. Norton & Company. 41 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Signed and Unsigned Characters Arithmetic Types • C89 uses the term integral types to refer to both • C99 has a more complicated hierarchy: the integer types and the character types. – Integer types • Enumerated types are also integral types. • char • Signed integer types, both standard (signed char, short • C99 doesn’t use the term “integral types.” int, int, long int, long long int) and extended • Instead, it expands the meaning of “integer types” • Unsigned integer types, both standard (unsigned char, unsigned short int, unsigned int, unsigned long to include the character types and the enumerated int, unsigned long long int, _Bool) and extended types. • Enumerated types • C99’s _Bool type is considered to be an unsigned – Floating types integer type. • Real floating types (float, double, long double) • Complex types (float _Complex, double _Complex, long double _Complex)

42 Copyright © 2008 W. W. Norton & Company. 44 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Arithmetic Types Escape Sequences • The integer types and floating types are • A character constant is usually one character collectively known as arithmetic types. enclosed in single quotes. • A summary of the arithmetic types in C89, divided • However, certain special characters—including into categories and subcategories: the new-line character—can’t be written in this – Integral types way, because they’re invisible (nonprinting) or • char because they can’t be entered from the keyboard. • Signed integer types (signed char, short int, int, long int) • Escape sequences provide a way to represent • Unsigned integer types (unsigned char, unsigned these characters. short int, unsigned int, unsigned long int) • There are two kinds of escape sequences: • Enumerated types character escapes and numeric escapes. – Floating types (float, double, long double)

43 Copyright © 2008 W. W. Norton & Company. 45 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Escape Sequences Escape Sequences • A complete list of character escapes: • An octal escape sequence consists of the \ Name Escape Sequence character followed by an octal number with at Alert (bell) \a most three digits, such as \33 or \033. Backspace \b \x Form feed \f • A hexadecimal escape sequence consists of New line \n followed by a hexadecimal number, such as \x1b Carriage return \r or \x1B. Horizontal tab \t • The x must be in lower case, but the hex digits can Vertical tab \v Backslash \\ be upper or lower case. Question mark \? Single quote \' Double quote \"

46 Copyright © 2008 W. W. Norton & Company. 48 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Escape Sequences Escape Sequences • Character escapes are handy, but they don’t exist • When used as a character constant, an escape for all nonprinting ASCII characters. sequence must be enclosed in single quotes. • Character escapes are also useless for representing • For example, a constant representing the escape characters beyond the basic 128 ASCII characters. character would be written '\33' (or '\x1b'). • Numeric escapes, which can represent any • Escape sequences tend to get a bit cryptic, so it’s character, are the solution to this problem. often a good idea to use #define to give them • A numeric escape for a particular character uses names: the character’s octal or hexadecimal value. #define ESC '\33' • For example, the ASCII (decimal • Escape sequences can be embedded in strings as value: 27) has the value 33 in octal and 1B in hex. well.

47 Copyright © 2008 W. W. Norton & Company. 49 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Reading and Writing Characters Character-Handling Functions Using scanf and printf • Calling C’s toupper library function is a fast • Since scanf doesn’t normally skip white space, and portable way to convert case: it’s easy to detect the end of an input line: check to ch = toupper(ch); see if the character just read is the new-line • toupper returns the upper-case version of its character. argument. • A loop that reads and ignores all remaining • Programs that call toupper need to have the characters in the current input line: following # at the top: do { scanf("%c", &ch); #include } while (ch != '\n'); • The C library provides many other useful • When scanf is called the next time, it will read character-handling functions. the first character on the next input line.

50 Copyright © 2008 W. W. Norton & Company. 52 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Reading and Writing Characters Reading and Writing Characters Using scanf and printf Using getchar and putchar • The %c conversion specification allows scanf and • For single-character input and output, getchar and printf to read and write single characters: putchar are an alternative to scanf and printf. char ch; • putchar writes a character: scanf("%c", &ch); /* reads one character */ putchar(ch); printf("%c", ch); /* writes one character */ • Each time getchar is called, it reads one character, • scanf doesn’t skip white-space characters. which it returns: • To force scanf to skip white space before reading a ch = getchar(); character, put a space in its format string just before %c: • getchar returns an int value rather than a char scanf(" %c", &ch); value, so ch will often have type int. • Like scanf, getchar doesn’t skip white-space characters as it reads.

51 Copyright © 2008 W. W. Norton & Company. 53 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Reading and Writing Characters Reading and Writing Characters Using getchar and putchar Using getchar and putchar • Using getchar and putchar (rather than • Moving the call of getchar into the controlling scanf and printf) saves execution time. expression allows us to condense the loop: – getchar and putchar are much simpler than while ((ch = getchar()) != '\n') scanf and printf, which are designed to read and ; write many kinds of data in a variety of formats. • The ch variable isn’t even needed; we can just – They are usually implemented as macros for additional compare the return value of getchar with the speed. new-line character: • getchar has another advantage. Because it while (getchar() != '\n') returns the character that it reads, getchar lends ; itself to various C idioms.

54 Copyright © 2008 W. W. Norton & Company. 56 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Reading and Writing Characters Reading and Writing Characters Using getchar and putchar Using getchar and putchar • Consider the scanf loop that we used to skip the • getchar is useful in loops that skip characters as rest of an input line: well as loops that search for characters. do { • A statement that uses getchar to skip an scanf("%c", &ch); indefinite number of blank characters: } while (ch != '\n'); while ((ch = getchar()) == ' ') • Rewriting this loop using getchar gives us the ; following: • When the loop terminates, ch will contain the first do { nonblank character that getchar encountered. ch = getchar(); } while (ch != '\n');

55 Copyright © 2008 W. W. Norton & Company. 57 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Reading and Writing Characters length.c Using getchar and putchar /* Determines the length of a message */ • Be careful when mixing getchar and scanf. #include • scanf has a tendency to leave behind characters that it int main(void) has “peeked” at but not read, including the new-line { char ch; character: int len = 0; printf("Enter an integer: "); printf("Enter a message: "); scanf("%d", &i); ch = getchar(); printf("Enter a command: "); while (ch != '\n') { command = getchar(); len++; ch = getchar(); scanf will leave behind any characters that weren’t } consumed during the reading of i, including (but not printf("Your message was %d character(s) long.\n", len); limited to) the new-line character. return 0; • getchar will fetch the first leftover character. }

58 Copyright © 2008 W. W. Norton & Company. 60 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Program: Determining the length2.c Length of a Message /* Determines the length of a message */ • The length.c program displays the length of a message #include entered by the user: int main(void) Enter a message: Brevity is the soul of wit. { Your message was 27 character(s) long. int len = 0; • The length includes spaces and punctuation, but not the printf("Enter a message: "); new-line character at the end of the message. while (getchar() != '\n') • We could use either scanf or getchar to read len++; printf("Your message was %d character(s) long.\n", len); characters; most C programmers would choose getchar. return 0; • length2.c is a shorter program that eliminates the } variable used to store the character read by getchar.

59 Copyright © 2008 W. W. Norton & Company. 61 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Type Conversion Type Conversion • For a computer to perform an arithmetic operation, the • Implicit conversions are performed: operands must usually be of the same size (the same – When the operands in an arithmetic or logical expression number of bits) and be stored in the same way. don’t have the same type. (C performs what are known as • When operands of different types are mixed in the usual arithmetic conversions.) expressions, the C compiler may have to generate – When the type of the expression on the right side of an instructions that change the types of some operands so assignment doesn’t match the type of the variable on the left side. that hardware will be able to evaluate the expression. – When the type of an argument in a function call doesn’t – If we add a 16-bit short and a 32-bit int, the compiler match the type of the corresponding parameter. will arrange for the short value to be converted to 32 bits. – When the type of the expression in a return statement – If we add an int and a float, the compiler will arrange for the int to be converted to float format. doesn’t match the function’s return type. • Chapter 9 discusses the last two cases.

62 Copyright © 2008 W. W. Norton & Company. 64 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Type Conversion The Usual Arithmetic Conversions • Because the compiler handles these conversions • The usual arithmetic conversions are applied to the operands automatically, without the programmer’s of most binary operators. involvement, they’re known as implicit • If f has type float and i has type int, the usual conversions. arithmetic conversions will be applied to the operands in the expression f+i. • C also allows the programmer to perform explicit • Clearly it’s safer to convert i to type float (matching f’s conversions, using the cast operator. type) rather than convert f to type int (matching i’s type). • The rules for performing implicit conversions are – When an integer is converted to float, the worst that can happen is somewhat complex, primarily because C has so a minor loss of precision. – Converting a floating-point number to int, on the other hand, many different arithmetic types. causes the fractional part of the number to be lost. Worse still, the result will be meaningless if the original number is larger than the largest possible integer or smaller than the smallest integer.

63 Copyright © 2008 W. W. Norton & Company. 65 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types The Usual Arithmetic Conversions The Usual Arithmetic Conversions • Strategy behind the usual arithmetic conversions: convert • Neither operand type is a floating type. First operands to the “narrowest” type that will safely perform integral promotion on both operands. accommodate both values. • Operand types can often be made to match by converting the • Then use the following diagram to promote the operand of the narrower type to the type of the other operand operand whose type is narrower: (this act is known as promotion). unsigned long int • Common promotions include the integral promotions, which convert a character or short integer to type int (or to long int unsigned int in some cases). • The rules for performing the usual arithmetic conversions can unsigned int be divided into two cases: – The type of either operand is a floating type. int – Neither operand type is a floating type.

66 Copyright © 2008 W. W. Norton & Company. 68 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types The Usual Arithmetic Conversions The Usual Arithmetic Conversions • The type of either operand is a floating type. • When a signed operand is combined with an – If one operand has type long double, then convert unsigned operand, the signed operand is converted the other operand to type long double. to an unsigned value. – Otherwise, if one operand has type double, convert • This rule can cause obscure programming errors. the other operand to type double. • It’s best to use unsigned integers as little as – Otherwise, if one operand has type float, convert the other operand to type float. possible and, especially, never mix them with • Example: If one operand has type long int and signed integers. the other has type double, the long int operand is converted to double.

67 Copyright © 2008 W. W. Norton & Company. 69 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types The Usual Arithmetic Conversions Conversion During Assignment • Example of the usual arithmetic conversions: • Assigning a floating-point number to an integer char c; short int s; variable drops the fractional part of the number: int i; unsigned int u; int i; long int l; unsigned long int ul; i = 842.97; /* i is now 842 */ float f; i = -842.97; /* i is now -842 */ double d; long double ld; • Assigning a value to a variable of a narrower type i = i + c; /* c is converted to int */ i = i + s; /* s is converted to int */ will give a meaningless result (or worse) if the u = u + i; /* i is converted to unsigned int */ value is outside the range of the variable’s type: l = l + u; /* u is converted to long int */ ul = ul + l; /* l is converted to unsigned long int */ c = 10000; /*** WRONG ***/ f = f + ul; /* ul is converted to float */ d = d + f; /* f is converted to double */ i = 1.0e20; /*** WRONG ***/ ld = ld + d; /* d is converted to long double */ f = 1.0e100; /*** WRONG ***/

70 Copyright © 2008 W. W. Norton & Company. 72 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Conversion During Assignment Conversion During Assignment • The usual arithmetic conversions don’t apply to • It’s a good idea to append the f suffix to a assignment. floating-point constant if it will be assigned to a • Instead, the expression on the right side of the float variable: assignment is converted to the type of the variable on f = 3.14159f; the left side: • Without the suffix, the constant 3.14159 would char c; have type double, possibly causing a warning int i; float f; message. double d; i = c; /* c is converted to int */ f = i; /* i is converted to float */ d = f; /* f is converted to double */

71 Copyright © 2008 W. W. Norton & Company. 73 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Implicit Conversions in C99 Implicit Conversions in C99 • C99’s rules for implicit conversions are somewhat different. • Neither operand type is a floating type. Perform integer • Each integer type has an “integer conversion rank.” promotion on both operands. Stop if the types of the operands • Ranks from highest to lowest: are now the same. Otherwise, use the following rules: 1. long long int, unsigned long long int – If both operands have signed types or both have unsigned types, convert the operand whose type has lesser integer conversion rank 2. long int, unsigned long int to the type of the operand with greater rank. 3. int, unsigned int – If the unsigned operand has rank greater or equal to the rank of the 4. short int, unsigned short int type of the signed operand, convert the signed operand to the type char signed char unsigned char 5. , , of the unsigned operand. 6. _Bool – If the type of the signed operand can represent all of the values of • C99’s “integer promotions” involve converting any type the type of the unsigned operand, convert the unsigned operand to whose rank is less than int and unsigned int to int the type of the signed operand. (provided that all values of the type can be represented using – Otherwise, convert both operands to the unsigned type int) or else to unsigned int. corresponding to the type of the signed operand.

74 Copyright © 2008 W. W. Norton & Company. 76 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Implicit Conversions in C99 Implicit Conversions in C99 • C99’s rules for performing the usual arithmetic • All arithmetic types can be converted to _Bool conversions can be divided into two cases: type. The result of the conversion is 0 if the – The type of either operand is a floating type. original value is 0; otherwise, the result is 1. – Neither operand type is a floating type. • The type of either operand is a floating type. As long as neither operand has a complex type, the rules are the same as before. (The conversion rules for complex types are discussed in Chapter 27.)

75 Copyright © 2008 W. W. Norton & Company. 77 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Casting Casting • Although C’s implicit conversions are convenient, • Cast expressions also let us force the compiler to we sometimes need a greater degree of control perform conversions. over type conversion. • Example: • For this reason, C provides casts. float quotient; int dividend, divisor; • A cast expression has the form quotient = dividend / divisor; ( type-name ) expression • To avoid truncation during division, we need to cast type-name specifies the type to which the one of the operands: expression should be converted. quotient = (float) dividend / divisor; • Casting dividend to float causes the compiler to convert divisor to float also.

78 Copyright © 2008 W. W. Norton & Company. 80 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Casting Casting • Using a cast expression to compute the fractional • C regards ( type-name ) as a unary operator. part of a float value: • Unary operators have higher precedence than float f, frac_part; binary operators, so the compiler interprets frac_part = f - (int) f; (float) dividend / divisor • The difference between f and (int) f is the as fractional part of f, which was dropped during the ((float) dividend) / divisor cast. • Other ways to accomplish the same effect: • Cast expressions enable us to document type quotient = dividend / (float) divisor; conversions that would take place anyway: quotient = (float) dividend / (float) divisor; i = (int) f; /* f is converted to int */

79 Copyright © 2008 W. W. Norton & Company. 81 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Casting Advantages of Type Definitions • Casts are sometimes necessary to avoid overflow: • Type definitions can make a program more long i; understandable. int j = 1000; • If the variables cash_in and cash_out will be i = j * j; /* overflow may occur */ used to store dollar amounts, declaring Dollars • Using a cast avoids the problem: as i = (long) j * j; typedef float Dollars; • The statement and then writing i = (long) (j * j); /*** WRONG ***/ Dollars cash_in, cash_out; wouldn’t work, since the overflow would already is more informative than just writing have occurred by the time of the cast. float cash_in, cash_out;

82 Copyright © 2008 W. W. Norton & Company. 84 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Type Definitions Advantages of Type Definitions • The #define directive can be used to create a • Type definitions can also make a program easier “Boolean type” macro: to modify. #define BOOL int • To redefine Dollars as double, only the type • There’s a better way using a feature known as a definition need be changed: type definition: typedef double Dollars; typedef int Bool; • Without the type definition, we would need to • Bool can now be used in the same way as the locate all float variables that store dollar built-in type names. amounts and change their declarations. • Example: Bool flag; /* same as int flag; */

83 Copyright © 2008 W. W. Norton & Company. 85 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types Type Definitions and Portability Type Definitions and Portability • Type definitions are an important tool for writing • Instead of using the int type to declare quantity portable programs. variables, we can define our own “quantity” type: • One of the problems with moving a program from typedef int Quantity; one computer to another is that types may have and use this type to declare variables: different ranges on different machines. Quantity q; • If i is an int variable, an assignment like • When we transport the program to a machine with i = 100000; shorter integers, we’ll change the type definition: is fine on a machine with 32-bit integers, but will typedef long Quantity; fail on a machine with 16-bit integers. • Note that changing the definition of Quantity may affect the way Quantity variables are used.

86 Copyright © 2008 W. W. Norton & Company. 88 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 7: Basic Types Type Definitions and Portability Type Definitions and Portability • For greater portability, consider using typedef • The C library itself uses typedef to create to define new names for integer types. names for types that can vary from one C • Suppose that we’re writing a program that needs implementation to another; these types often have variables capable of storing product quantities in names that end with _t. the range 0–50,000. • Typical definitions of these types: • We could use long variables for this purpose, but typedef long int ptrdiff_t; we’d rather use int variables, since arithmetic on typedef unsigned long int size_t; int values may be faster than operations on typedef int wchar_t; long values. Also, int variables may take up • In C99, the header uses typedef less space. to define names for integer types with a particular number of bits.

87 Copyright © 2008 W. W. Norton & Company. 89 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 7: Basic Types Chapter 7: Basic Types The sizeof Operator The sizeof Operator • The value of the expression • Printing a sizeof value requires care, because the type of a sizeof expression is an implementation-defined type sizeof ( type-name ) named size_t. is an unsigned integer representing the number of • In C89, it’s best to convert the value of the expression to a bytes required to store a value belonging to type- known type before printing it: name. printf("Size of int: %lu\n", • sizeof(char) is always 1, but the sizes of the (unsigned long) sizeof(int)); other types may vary. • The printf function in C99 can display a size_t value directly if the letter z is included in the conversion • On a 32-bit machine, sizeof(int) is normally specification: 4. printf("Size of int: %zu\n", sizeof(int));

90 Copyright © 2008 W. W. Norton & Company. 92 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 7: Basic Types Chapter 8: Arrays The sizeof Operator • The sizeof operator can also be applied to constants, variables, and expressions in general. – If i and j are int variables, then sizeof(i) is 4 on a 32-bit machine, as is sizeof(i + j). Chapter 8 • When applied to an expression—as opposed to a type—sizeof doesn’t require parentheses. Arrays – We could write sizeof i instead of sizeof(i). • Parentheses may be needed anyway because of operator precedence. – The compiler interprets sizeof i + j as (sizeof i) + j, because sizeof takes precedence over binary +.

91 Copyright © 2008 W. W. Norton & Company. 1 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays Scalar Variables versus Aggregate Variables One-Dimensional Arrays • So far, the only variables we’ve seen are scalar: • To declare an array, we must specify the type of capable of holding a single data item. the array’s elements and the number of elements: • C also supports aggregate variables, which can int a[10]; store collections of values. • The elements may be of any type; the length of the • There are two kinds of aggregates in C: arrays and array can be any (integer) constant expression. structures. • Using a macro to define the length of an array is • The focus of the chapter is on one-dimensional an excellent practice: arrays, which play a much bigger role in C than do #define N 10 multidimensional arrays. … int a[N];

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays One-Dimensional Arrays Array Subscripting • An array is a data structure containing a number of • To access an array element, write the array name data values, all of which have the same type. followed by an integer value in square brackets. • These values, known as elements, can be individually • This is referred to as subscripting or indexing the selected by their position within the array. array. • The simplest kind of array has just one dimension. • The elements of an array of length n are indexed • The elements of a one-dimensional array a are from 0 to n – 1. conceptually arranged one after another in a single • If a is an array of length 10, its elements are row (or column): designated by a[0], a[1], …, a[9]:

3 Copyright © 2008 W. W. Norton & Company. 5 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays Array Subscripting Array Subscripting • Expressions of the form a[i] are lvalues, so they • C doesn’t require that subscript bounds be can be used in the same way as ordinary variables: checked; if a subscript goes out of range, the a[0] = 1; program’s behavior is undefined. printf("%d\n", a[5]); • A common mistake: forgetting that an array with n ++a[i]; elements is indexed from 0 to n – 1, not 1 to n: • In general, if an array contains elements of type T, int a[10], i; then each element of the array is treated as if it were a variable of type T. for (i = 1; i <= 10; i++) a[i] = 0; With some compilers, this innocent-looking for statement causes an infinite loop.

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays Array Subscripting Array Subscripting • Many programs contain for loops whose job is to perform • An array subscript may be any integer expression: some operation on every element in an array. a[i+j*10] = 0; • Examples of typical operations on an array a of length N: • The expression can even have side effects: for (i = 0; i < N; i++) a[i] = 0; /* clears a */ i = 0; while (i < N) for (i = 0; i < N; i++) scanf("%d", &a[i]); /* reads data into a */ a[i++] = 0;

for (i = 0; i < N; i++) sum += a[i]; /* sums the elements of a */

7 Copyright © 2008 W. W. Norton & Company. 9 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays Array Subscripting reverse.c /* Reverses a series of numbers */

• Be careful when an array subscript has a side effect: #include i = 0; #define N 10 while (i < N) a[i] = b[i++]; int main(void) { • The expression a[i] = b[i++] accesses the value int a[N], i; of i and also modifies i, causing undefined behavior. printf("Enter %d numbers: ", N); for (i = 0; i < N; i++) • The problem can be avoided by removing the scanf("%d", &a[i]); increment from the subscript: printf("In reverse order:"); for (i = N - 1; i >= 0; i--) for (i = 0; i < N; i++) printf(" %d", a[i]); a[i] = b[i]; printf("\n"); return 0; }

10 Copyright © 2008 W. W. Norton & Company. 12 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays Program: Reversing a Series of Numbers Array Initialization • The reverse.c program prompts the user to • An array, like any other variable, can be given an enter a series of numbers, then writes the numbers initial value at the time it’s declared. in reverse order: • The most common form of array initializer is a Enter 10 numbers: 34 82 49 102 7 94 23 11 50 31 list of constant expressions enclosed in braces and In reverse order: 31 50 11 23 94 7 102 49 82 34 separated by commas: • The program stores the numbers in an array as int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; they’re read, then goes through the array backwards, printing the elements one by one.

11 Copyright © 2008 W. W. Norton & Company. 13 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays Array Initialization Designated Initializers (C99) • If the initializer is shorter than the array, the remaining • It’s often the case that relatively few elements of elements of the array are given the value 0: an array need to be initialized explicitly; the other int a[10] = {1, 2, 3, 4, 5, 6}; /* initial value of a is {1, 2, 3, 4, 5, 6, 0, 0, 0, 0} */ elements can be given default values. • Using this feature, we can easily initialize an array to all • An example: zeros: int a[15] = int a[10] = {0}; {0, 0, 29, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 48}; /* initial value of a is {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} */ • For a large array, writing an initializer in this There’s a single 0 inside the braces because it’s illegal for fashion is tedious and error-prone. an initializer to be completely empty. • It’s also illegal for an initializer to be longer than the array it initializes.

14 Copyright © 2008 W. W. Norton & Company. 16 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays Array Initialization Designated Initializers (C99) • If an initializer is present, the length of the array • C99’s designated initializers can be used to solve may be omitted: this problem. int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; • Here’s how we could redo the previous example • The compiler uses the length of the initializer to using a designated initializer: determine how long the array is. int a[15] = {[2] = 29, [9] = 7, [14] = 48}; • Each number in brackets is said to be a designator.

15 Copyright © 2008 W. W. Norton & Company. 17 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays Designated Initializers (C99) Designated Initializers (C99) • Designated initializers are shorter and easier to • An initializer may use both the older (element-by- read (at least for some arrays). element) technique and the newer (designated) • Also, the order in which the elements are listed no technique: longer matters. int c[10] = {5, 1, 9, [4] = 3, 7, 2, [8] = 6}; • Another way to write the previous example: int a[15] = {[14] = 48, [9] = 7, [2] = 29};

18 Copyright © 2008 W. W. Norton & Company. 20 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays

Designated Initializers (C99) Program: Checking a Number for Repeated Digits • Designators must be integer constant expressions. • The repdigit.c program checks whether any • If the array being initialized has length n, each of the digits in a number appear more than once. designator must be between 0 and n – 1. • After the user enters a number, the program prints • If the length of the array is omitted, a designator either Repeated digit or No repeated can be any nonnegative integer. digit: – The compiler will deduce the length of the array from Enter a number: 28212 the largest designator. Repeated digit • The following array will have 24 elements: • The number 28212 has a repeated digit (2); a int b[] = {[5] = 10, [23] = 13, [11] = 36, [15] = 29}; number like 9357 doesn’t.

19 Copyright © 2008 W. W. Norton & Company. 21 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays

if (n > 0) Program: Checking a Number for Repeated Digits printf("Repeated digit\n"); else • The program uses an array of 10 Boolean values to keep printf("No repeated digit\n"); track of which digits appear in a number. return 0; • Initially, every element of the digit_seen array is } false. • When given a number n, the program examines n’s digits one at a time, storing the current digit in a variable named digit. – If digit_seen[digit] is true, then digit appears at least twice in n. – If digit_seen[digit] is false, then digit has not been seen before, so the program sets digit_seen[digit] to true and keeps going.

22 Copyright © 2008 W. W. Norton & Company. 24 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays repdigit.c Using the sizeof Operator with Arrays /* Checks numbers for repeated digits */ sizeof #include /* C99 only */ • The operator can determine the size of #include an array (in bytes). int main(void) • If a is an array of 10 integers, then sizeof(a) { bool digit_seen[10] = {false}; is typically 40 (assuming that each integer requires int digit; long n; four bytes). printf("Enter a number: "); • We can also use sizeof to measure the size of scanf("%ld", &n); while (n > 0) { an array element, such as a[0]. digit = n % 10; if (digit_seen[digit]) • Dividing the array size by the element size gives break; digit_seen[digit] = true; the length of the array: n /= 10; } sizeof(a) / sizeof(a[0])

23 Copyright © 2008 W. W. Norton & Company. 25 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays Using the sizeof Operator with Arrays Using the sizeof Operator with Arrays • Some programmers use this expression when the • To avoid a warning, we can add a cast that length of the array is needed. converts sizeof(a) / sizeof(a[0]) to a • A loop that clears the array a: signed integer: for (i = 0; i < sizeof(a) / sizeof(a[0]); i++) for (i = 0; i < (int) (sizeof(a) / sizeof(a[0])); i++) a[i] = 0; a[i] = 0; Note that the loop doesn’t have to be modified if • Defining a macro for the size calculation is often the array length should change at a later date. helpful: #define SIZE ((int) (sizeof(a) / sizeof(a[0]))) for (i = 0; i < SIZE; i++) a[i] = 0;

26 Copyright © 2008 W. W. Norton & Company. 28 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays Using the sizeof Operator with Arrays Program: Computing Interest • Some compilers produce a warning message for the • The interest.c program prints a table expression i < sizeof(a) / sizeof(a[0]). showing the value of $100 invested at different • The variable i probably has type int (a signed rates of interest over a period of years. type), whereas sizeof produces a value of type • The user will enter an interest rate and the number size_t (an unsigned type). of years the money will be invested. • Comparing a signed integer with an unsigned • The table will show the value of the money at one- integer can be dangerous, but in this case it’s safe. year intervals—at that interest rate and the next four higher rates—assuming that interest is compounded once a year.

27 Copyright © 2008 W. W. Norton & Company. 29 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays Program: Computing Interest interest.c /* Prints a table of compound interest */ • Here’s what a session with the program will look #include like: #define NUM_RATES ((int) (sizeof(value) / sizeof(value[0]))) Enter interest rate: 6 #define INITIAL_BALANCE 100.00 Enter number of years: 5 int main(void) Years 6% 7% 8% 9% 10% { 1 106.00 107.00 108.00 109.00 110.00 int i, low_rate, num_years, year; double value[5]; 2 112.36 114.49 116.64 118.81 121.00 3 119.10 122.50 125.97 129.50 133.10 printf("Enter interest rate: "); 4 126.25 131.08 136.05 141.16 146.41 scanf("%d", &low_rate); printf("Enter number of years: "); 5 133.82 140.26 146.93 153.86 161.05 scanf("%d", &num_years);

30 Copyright © 2008 W. W. Norton & Company. 32 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays

printf("\nYears"); Program: Computing Interest for (i = 0; i < NUM_RATES; i++) { printf("%6d%%", low_rate + i); • The numbers in the second row depend on the value[i] = INITIAL_BALANCE; } numbers in the first row, so it makes sense to store printf("\n");

the first row in an array. for (year = 1; year <= num_years; year++) { – The values in the array are then used to compute the printf("%3d ", year); for (i = 0; i < NUM_RATES; i++) { second row. value[i] += (low_rate + i) / 100.0 * value[i]; – This process can be repeated for the third and later rows. printf("%7.2f", value[i]); } • The program uses nested for statements. printf("\n"); – The outer loop counts from 1 to the number of years } requested by the user. return 0; – The inner loop increments the interest rate from its lowest } value to its highest value.

31 Copyright © 2008 W. W. Norton & Company. 33 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays Multidimensional Arrays Multidimensional Arrays • An array may have any number of dimensions. • Although we visualize two-dimensional arrays as • The following declaration creates a two-dimensional array tables, that’s not the way they’re actually stored in (a matrix, in mathematical terminology): computer memory. int m[5][9]; • C stores arrays in row-major order, with row 0 •mhas 5 rows and 9 columns. Both rows and columns are first, then row 1, and so forth. indexed from 0: • How the m array is stored:

34 Copyright © 2008 W. W. Norton & Company. 36 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays Multidimensional Arrays Multidimensional Arrays • To access the element of m in row i, column j, • Nested for loops are ideal for processing we must write m[i][j]. multidimensional arrays. • The expression m[i] designates row i of m, and • Consider the problem of initializing an array for use as an identity matrix. A pair of nested for loops is perfect: m[i][j] then selects element j in this row. #define N 10 • Resist the temptation to write m[i,j] instead of double ident[N][N]; m[i][j]. int row, col; • C treats the comma as an operator in this context, for (row = 0; row < N; row++) for (col = 0; col < N; col++) so m[i,j] is the same as m[j]. if (row == col) ident[row][col] = 1.0; else ident[row][col] = 0.0;

35 Copyright © 2008 W. W. Norton & Company. 37 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays Initializing a Multidimensional Array Initializing a Multidimensional Array • We can create an initializer for a two-dimensional • If an inner list isn’t long enough to fill a row, the array by nesting one-dimensional initializers: remaining elements in the row are initialized to 0: int m[5][9] = {{1, 1, 1, 1, 1, 0, 1, 1, 1}, int m[5][9] = {{1, 1, 1, 1, 1, 0, 1, 1, 1}, {0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 1, 0, 1, 0, 1, 0, 1}, {0, 1, 0, 1, 1, 0, 0, 1, 0}, {0, 1, 0, 1, 1, 0, 0, 1}, {1, 1, 0, 1, 0, 0, 0, 1, 0}, {1, 1, 0, 1, 0, 0, 0, 1}, {1, 1, 0, 1, 0, 0, 1, 1, 1}}; {1, 1, 0, 1, 0, 0, 1, 1, 1}}; • Initializers for higher-dimensional arrays are constructed in a similar fashion. • C provides a variety of ways to abbreviate initializers for multidimensional arrays

38 Copyright © 2008 W. W. Norton & Company. 40 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays Initializing a Multidimensional Array Initializing a Multidimensional Array • If an initializer isn’t large enough to fill a • We can even omit the inner braces: multidimensional array, the remaining elements int m[5][9] = {1, 1, 1, 1, 1, 0, 1, 1, 1, are given the value 0. 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, • The following initializer fills only the first three 1, 1, 0, 1, 0, 0, 0, 1, 0, rows of m; the last two rows will contain zeros: 1, 1, 0, 1, 0, 0, 1, 1, 1}; int m[5][9] = {{1, 1, 1, 1, 1, 0, 1, 1, 1}, Once the compiler has seen enough values to fill {0, 1, 0, 1, 0, 1, 0, 1, 0}, one row, it begins filling the next. {0, 1, 0, 1, 1, 0, 0, 1, 0}}; • Omitting the inner braces can be risky, since an extra element (or even worse, a missing element) will affect the rest of the initializer.

39 Copyright © 2008 W. W. Norton & Company. 41 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays Initializing a Multidimensional Array Constant Arrays • C99’s designated initializers work with • Advantages of declaring an array to be const: multidimensional arrays. – Documents that the program won’t change the array. • How to create 2 × 2 identity matrix: – Helps the compiler catch errors. double ident[2][2] = {[0][0] = 1.0, [1][1] = 1.0}; • const isn’t limited to arrays, but it’s particularly As usual, all elements for which no value is useful in array declarations. specified will default to zero.

42 Copyright © 2008 W. W. Norton & Company. 44 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays Constant Arrays Program: Dealing a Hand of Cards • An array can be made “constant” by starting its • The deal.c program illustrates both two- declaration with the word const: dimensional arrays and constant arrays. const char hex_chars[] = • The program deals a random hand from a standard {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; deck of playing cards. • An array that’s been declared const should not • Each card in a standard deck has a suit (clubs, be modified by the program. diamonds, hearts, or spades) and a rank (two, three, four, five, six, seven, eight, nine, ten, jack, queen, king, or ace).

43 Copyright © 2008 W. W. Norton & Company. 45 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays Program: Dealing a Hand of Cards Program: Dealing a Hand of Cards • The user will specify how many cards should be in • The in_hand array is used to keep track of which the hand: cards have already been chosen. Enter number of cards in hand: 5 • The array has 4 rows and 13 columns; each element Your hand: 7c 2s 5d as 2h corresponds to one of the 52 cards in the deck. • Problems to be solved: • All elements of the array will be false to start with. – How do we pick cards randomly from the deck? • Each time we pick a card at random, we’ll check – How do we avoid picking the same card twice? whether the element of in_hand corresponding to that card is true or false. – If it’s true, we’ll have to pick another card. – If it’s false, we’ll store true in that element to remind us later that this card has already been picked.

46 Copyright © 2008 W. W. Norton & Company. 48 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays Program: Dealing a Hand of Cards Program: Dealing a Hand of Cards • To pick cards randomly, we’ll use several C • Once we’ve verified that a card is “new,” we’ll library functions: need to translate its numerical rank and suit into – time (from ) – returns the current time, characters and then display the card. encoded in a single number. • To translate the rank and suit to character form, – srand (from ) – initializes C’s random we’ll set up two arrays of characters—one for the number generator. rank and one for the suit—and then use the – rand (from ) – produces an apparently numbers to subscript the arrays. random number each time it’s called. • By using the % operator, we can scale the return • These arrays won’t change during program execution, so they are declared to be const. value from rand so that it falls between 0 and 3 (for suits) or between 0 and 12 (for ranks).

47 Copyright © 2008 W. W. Norton & Company. 49 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays deal.c Variable-Length Arrays (C99) /* Deals a random hand of cards */ • In C89, the length of an array variable must be #include /* C99 only */ #include specified by a constant expression. #include #include • In C99, however, it’s sometimes possible to use an

#define NUM_SUITS 4 expression that’s not constant. #define NUM_RANKS 13 • The reverse2.c program—a modification of int main(void) reverse.c—illustrates this ability. { bool in_hand[NUM_SUITS][NUM_RANKS] = {false}; int num_cards, rank, suit; const char rank_code[] = {'2','3','4','5','6','7','8', '9','t','j','q','k','a'}; const char suit_code[] = {'c','d','h','s'};

50 Copyright © 2008 W. W. Norton & Company. 52 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 8: Arrays srand((unsigned) time(NULL)); reverse2.c printf("Enter number of cards in hand: "); /* Reverses a series of numbers using a variable-length scanf("%d", &num_cards); array - C99 only */ printf("Your hand:"); #include while (num_cards > 0) { suit = rand() % NUM_SUITS; /* picks a random suit */ int main(void) rank = rand() % NUM_RANKS; /* picks a random rank */ { if (!in_hand[suit][rank]) { int i, n; in_hand[suit][rank] = true; num_cards--; printf("How many numbers do you want to reverse? "); printf(" %c%c", rank_code[rank], suit_code[suit]); scanf("%d", &n); } } int a[n]; /* C99 only - length of array depends on n */ printf("\n"); printf("Enter %d numbers: ", n); return 0; for (i = 0; i < n; i++) } scanf("%d", &a[i]);

51 Copyright © 2008 W. W. Norton & Company. 53 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 8: Arrays Chapter 8: Arrays

printf("In reverse order:"); for (i = n - 1; i >= 0; i--) Variable-Length Arrays (C99) printf(" %d", a[i]); printf("\n"); • The length of a VLA doesn’t have to be specified by return 0; a single variable. Arbitrary expressions are legal: } int a[3*i+5]; int b[j+k]; • Like other arrays, VLAs can be multidimensional: int c[m][n]; • Restrictions on VLAs: – Can’t have static storage duration (discussed in Chapter 18). – Can’t have an initializer.

54 Copyright © 2008 W. W. Norton & Company. 56 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 8: Arrays Chapter 9: Functions Variable-Length Arrays (C99) • The array a in the reverse2.c program is an example of a variable-length array (or VLA). • The length of a VLA is computed when the Chapter 9 program is executed. • The chief advantage of a VLA is that a program can calculate exactly how many elements are Functions needed. • If the programmer makes the choice, it’s likely that the array will be too long (wasting memory) or too short (causing the program to fail).

55 Copyright © 2008 W. W. Norton & Company. 1 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Introduction Program: Computing Averages • A function is a series of statements that have been • A function named average that computes the grouped together and given a name. average of two double values: • Each function is essentially a small program, with double average(double a, double b) its own declarations and statements. { return (a + b) / 2; • Advantages of functions: } – A program can be divided into small pieces that are • The word double at the beginning is the return easier to understand and modify. type of average. – We can avoid duplicating code that’s used more than once. • The identifiers a and b (the function’s – A function that was originally part of one program can parameters) represent the numbers that will be be reused in other programs. supplied when average is called.

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Defining and Calling Functions Program: Computing Averages • Before we go over the formal rules for defining a • Every function has an executable part, called the function, let’s look at three simple programs that body, which is enclosed in braces. define functions. • The body of average consists of a single return statement. • Executing this statement causes the function to “return” to the place from which it was called; the value of (a+b)/2will be the value returned by the function.

3 Copyright © 2008 W. W. Norton & Company. 5 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Program: Computing Averages Program: Computing Averages • A function call consists of a function name • The average.c program reads three numbers followed by a list of arguments. and uses the average function to compute their – average(x, y) is a call of the average function. averages, one pair at a time: • Arguments are used to supply information to a Enter three numbers: 3.5 9.6 10.2 function. Average of 3.5 and 9.6: 6.55 Average of 9.6 and 10.2: 9.9 – The call average(x, y) causes the values of x and y to be copied into the parameters a and b. Average of 3.5 and 10.2: 6.85 • An argument doesn’t have to be a variable; any expression of a compatible type will do. – average(5.1, 8.9) and average(x/2, y/3) are legal.

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Program: Computing Averages average.c /* Computes pairwise averages of three numbers */

• We’ll put the call of average in the place where #include

we need to use the return value. double average(double a, double b) { • A statement that prints the average of x and y: return (a + b) / 2; printf("Average: %g\n", average(x, y)); } int main(void) The return value of average isn’t saved; the { program prints it and then discards it. double x, y, z; printf("Enter three numbers: "); • If we had needed the return value later in the scanf("%lf%lf%lf", &x, &y, &z); printf("Average of %g and %g: %g\n", x, y, average(x, y)); program, we could have captured it in a variable: printf("Average of %g and %g: %g\n", y, z, average(y, z)); printf("Average of %g and %g: %g\n", x, z, average(x, z)); avg = average(x, y); return 0; }

7 Copyright © 2008 W. W. Norton & Company. 9 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Program: Printing a Countdown Program: Printing a Pun (Revisited) • To indicate that a function has no return value, we • When a function has no parameters, the word void is specify that its return type is void: placed in parentheses after the function’s name: void print_count(int n) void print_pun(void) { { printf("To C, or not to C: that is the question.\n"); printf("T minus %d and counting\n", n); } } • To call a function with no arguments, we write the • void is a type with no values. function’s name, followed by parentheses: • A call of print_count must appear in a statement by print_pun(); itself: The parentheses must be present. print_count(i); • The pun2.c program tests the print_pun function. • The countdown.c program calls print_count 10 times inside a loop.

10 Copyright © 2008 W. W. Norton & Company. 12 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions countdown.c pun2.c /* Prints a countdown */ /* Prints a bad pun */

#include #include void print_count(int n) void print_pun(void) { { printf("T minus %d and counting\n", n); printf("To C, or not to C: that is the question.\n"); } } int main(void) int main(void) { { int i; print_pun(); return 0; for (i = 10; i > 0; --i) } print_count(i);

return 0; }

11 Copyright © 2008 W. W. Norton & Company. 13 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Function Definitions Function Definitions • General form of a function definition: • As a matter of style, some programmers put the return-type function-name ( parameters ) return type above the function name: { double declarations average(double a, double b) statements { } return (a + b) / 2; } • Putting the return type on a separate line is especially useful if the return type is lengthy, like unsigned long int.

14 Copyright © 2008 W. W. Norton & Company. 16 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Function Definitions Function Definitions • The return type of a function is the type of value • After the function name comes a list of that the function returns. parameters. • Rules governing the return type: • Each parameter is preceded by a specification of – Functions may not return arrays. its type; parameters are separated by commas. – Specifying that the return type is void indicates that • If the function has no parameters, the word void the function doesn’t return a value. should appear between the parentheses. • If the return type is omitted in C89, the function is presumed to return a value of type int. • In C99, omitting the return type is illegal.

15 Copyright © 2008 W. W. Norton & Company. 17 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Function Definitions Function Definitions • The body of a function may include both • The body of a function whose return type is void declarations and statements. (a “void function”) can be empty: • An alternative version of the average function: void print_pun(void) double average(double a, double b) { { } double sum; /* declaration */ • Leaving the body empty may make sense as a temporary step during program development. sum = a + b; /* statement */ return sum / 2; /* statement */ }

18 Copyright © 2008 W. W. Norton & Company. 20 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Function Definitions Function Calls • Variables declared in the body of a function can’t • A function call consists of a function name be examined or modified by other functions. followed by a list of arguments, enclosed in • In C89, variable declarations must come first, parentheses: before all statements in the body of a function. average(x, y) print_count(i) • In C99, variable declarations and statements can print_pun() be mixed, as long as each variable is declared • If the parentheses are missing, the function won’t prior to the first statement that uses the variable. be called: print_pun; /*** WRONG ***/ This statement is legal but has no effect.

19 Copyright © 2008 W. W. Norton & Company. 21 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Function Calls Function Calls • A call of a void function is always followed by a • Ignoring the return value of average is an odd semicolon to turn it into a statement: thing to do, but for some functions it makes sense. print_count(i); • printf returns the number of characters that it print_pun(); prints. • A call of a non-void function produces a value that • After the following call, num_chars will have can be stored in a variable, tested, printed, or used in the value 9: some other way: num_chars = printf("Hi, Mom!\n"); avg = average(x, y); if (average(x, y) > 0) • We’ll normally discard printf’s return value: printf("Average is positive\n"); printf("Hi, Mom!\n"); printf("The average is %g\n", average(x, y)); /* discards return value */

22 Copyright © 2008 W. W. Norton & Company. 24 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Function Calls Function Calls • The value returned by a non-void function can • To make it clear that we’re deliberately discarding always be discarded if it’s not needed: the return value of a function, C allows us to put average(x, y); /* discards return value */ (void) before the call: This call is an example of an expression statement: (void) printf("Hi, Mom!\n"); a statement that evaluates an expression but then • Using (void) makes it clear to others that you discards the result. deliberately discarded the return value, not just forgot that there was one.

23 Copyright © 2008 W. W. Norton & Company. 25 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions

int main(void) Program: Testing Whether a Number Is Prime { int n;

• The prime.c program tests whether a number is printf("Enter a number: "); prime: scanf("%d", &n); if (is_prime(n)) Enter a number: 34 printf("Prime\n"); Not prime else printf("Not prime\n"); • The program uses a function named is_prime return 0; that returns true if its parameter is a prime } number and false if it isn’t. • is_prime divides its parameter n by each of the numbers between 2 and the square root of n; if the remainder is ever 0, n isn’t prime.

26 Copyright © 2008 W. W. Norton & Company. 28 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions prime.c Function Declarations /* Tests whether a number is prime */ • C doesn’t require that the definition of a function #include /* C99 only */ #include precede its calls. bool is_prime(int n) • Suppose that we rearrange the average.c { int divisor; program by putting the definition of average after the definition of main. if (n <= 1) return false; for (divisor = 2; divisor * divisor <= n; divisor++) if (n % divisor == 0) return false; return true; }

27 Copyright © 2008 W. W. Norton & Company. 29 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Function Declarations Function Declarations #include • The compiler is unable to check that we’re passing int main(void) { average the right number of arguments and that double x, y, z; the arguments have the proper type. printf("Enter three numbers: "); scanf("%lf%lf%lf", &x, &y, &z); • Instead, it performs the default argument printf("Average of %g and %g: %g\n", x, y, average(x, y)); promotions and hopes for the best. printf("Average of %g and %g: %g\n", y, z, average(y, z)); printf("Average of %g and %g: %g\n", x, z, average(x, z)); • When it encounters the definition of average return 0; later in the program, the compiler notices that the } function’s return type is actually double, not double average(double a, double b) { int, and so we get an error message. return (a + b) / 2; }

30 Copyright © 2008 W. W. Norton & Company. 32 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Function Declarations Function Declarations • When the compiler encounters the first call of • One way to avoid the problem of call-before- average in main, it has no information about definition is to arrange the program so that the the function. definition of each function precedes all its calls. • Instead of producing an error message, the • Unfortunately, such an arrangement doesn’t compiler assumes that average returns an int always exist. value. • Even when it does, it may make the program • We say that the compiler has created an implicit harder to understand by putting its function declaration of the function. definitions in an unnatural order.

31 Copyright © 2008 W. W. Norton & Company. 33 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Function Declarations Function Declarations • Fortunately, C offers a better solution: declare each • Function declarations of the kind we’re discussing function before calling it. are known as function prototypes. • A function declaration provides the compiler with a • C also has an older style of function declaration in brief glimpse at a function whose full definition will which the parentheses are left empty. appear later. • A function prototype doesn’t have to specify the • General form of a function declaration: names of the function’s parameters, as long as return-type function-name ( parameters ) ; their types are present: • The declaration of a function must be consistent with double average(double, double); the function’s definition. • It’s usually best not to omit parameter names. • Here’s the average.c program with a declaration of average added.

34 Copyright © 2008 W. W. Norton & Company. 36 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Function Declarations Function Declarations #include • C99 has adopted the rule that either a declaration double average(double a, double b); /* DECLARATION */ or a definition of a function must be present prior int main(void) { to any call of the function. double x, y, z; printf("Enter three numbers: "); • Calling a function for which the compiler has not scanf("%lf%lf%lf", &x, &y, &z); yet seen a declaration or definition is an error. printf("Average of %g and %g: %g\n", x, y, average(x, y)); printf("Average of %g and %g: %g\n", y, z, average(y, z)); printf("Average of %g and %g: %g\n", x, z, average(x, z)); return 0; } double average(double a, double b) /* DEFINITION */ { return (a + b) / 2; }

35 Copyright © 2008 W. W. Norton & Company. 37 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Arguments Arguments • In C, arguments are passed by value: when a • Consider the following function, which raises a function is called, each argument is evaluated and number x to a power n: its value assigned to the corresponding parameter. int power(int x, int n) • Since the parameter contains a copy of the { argument’s value, any changes made to the int i, result = 1; parameter during the execution of the function for (i = 1; i <= n; i++) don’t affect the argument. result = result * x;

return result; }

38 Copyright © 2008 W. W. Norton & Company. 40 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Arguments Arguments • The fact that arguments are passed by value has • Since n is a copy of the original exponent, the both advantages and disadvantages. function can safely modify it, removing the need • Since a parameter can be modified without for i: affecting the corresponding argument, we can use int power(int x, int n) parameters as variables within the function, { reducing the number of genuine variables needed. int result = 1; while (n-- > 0) result = result * x;

return result; }

39 Copyright © 2008 W. W. Norton & Company. 41 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Arguments Argument Conversions • C’s requirement that arguments be passed by value • C allows function calls in which the types of the makes it difficult to write certain kinds of functions. arguments don’t match the types of the • Suppose that we need a function that will decompose a parameters. double value into an integer part and a fractional part. • The rules governing how the arguments are • Since a function can’t return two numbers, we might try converted depend on whether or not the compiler passing a pair of variables to the function and having it has seen a prototype for the function (or the modify them: void decompose(double x, long int_part, function’s full definition) prior to the call. double frac_part) { int_part = (long) x; frac_part = x - int_part; }

42 Copyright © 2008 W. W. Norton & Company. 44 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Arguments Argument Conversions • A call of the function: • The compiler has encountered a prototype prior decompose(3.14159, i, d); to the call. • Unfortunately, i and d won’t be affected by the • The value of each argument is implicitly assignments to int_part and frac_part. converted to the type of the corresponding • Chapter 11 shows how to make decompose parameter as if by assignment. work correctly. • Example: If an int argument is passed to a function that was expecting a double, the argument is converted to double automatically.

43 Copyright © 2008 W. W. Norton & Company. 45 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Argument Conversions Argument Conversions • The compiler has not encountered a prototype • Instead, the compiler performs the default argument prior to the call. promotions on x, with no effect. • Since it’s expecting an argument of type int but has been • The compiler performs the default argument given a double value instead, the effect of calling square promotions: is undefined. – float arguments are converted to double. • The problem can be fixed by casting square’s argument to – The integral promotions are performed, causing char the proper type: and short arguments to be converted to int. (In C99, printf("Square: %d\n", square((int) x)); the integer promotions are performed.) • A much better solution is to provide a prototype for square before calling it. • In C99, calling square without first providing a declaration or definition of the function is an error.

46 Copyright © 2008 W. W. Norton & Company. 48 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Argument Conversions Array Arguments • Relying on the default argument promotions is dangerous. • When a function parameter is a one-dimensional • Example: array, the length of the array can be left unspecified: #include int f(int a[]) /* no length specified */ int main(void) { { double x = 3.0; … printf("Square: %d\n", square(x)); } return 0; } • C doesn’t provide any easy way for a function to int square(int n) determine the length of an array passed to it. { return n * n; • Instead, we’ll have to supply the length—if the } function needs it—as an additional argument. • At the time square is called, the compiler doesn’t know that it expects an argument of type int.

47 Copyright © 2008 W. W. Norton & Company. 49 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Array Arguments Array Arguments • Example: • When sum_array is called, the first argument will be the int sum_array(int a[], int n) name of an array, and the second will be its length: { #define LEN 100 int i, sum = 0; int main(void) for (i = 0; i < n; i++) { int b[LEN], total; sum += a[i]; … total = sum_array(b, LEN); return sum; … } } • Since sum_array needs to know the length of a, • Notice that we don’t put brackets after an array name when we must supply it as a second argument. passing it to a function: total = sum_array(b[], LEN); /*** WRONG ***/

50 Copyright © 2008 W. W. Norton & Company. 52 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Array Arguments Array Arguments • The prototype for sum_array has the following • A function has no way to check that we’ve passed appearance: it the correct array length. int sum_array(int a[], int n); • We can exploit this fact by telling the function that • As usual, we can omit the parameter names if we the array is smaller than it really is. wish: • Suppose that we’ve only stored 50 numbers in the int sum_array(int [], int); b array, even though it can hold 100. • We can sum just the first 50 elements by writing total = sum_array(b, 50);

51 Copyright © 2008 W. W. Norton & Company. 53 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Array Arguments Array Arguments • Be careful not to tell a function that an array • A call of store_zeros: argument is larger than it really is: store_zeros(b, 100); total = sum_array(b, 150); /*** WRONG ***/ • The ability to modify the elements of an array sum_array will go past the end of the array, argument may seem to contradict the fact that C causing undefined behavior. passes arguments by value. • Chapter 12 explains why there’s actually no contradiction.

54 Copyright © 2008 W. W. Norton & Company. 56 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Array Arguments Array Arguments • A function is allowed to change the elements of an • If a parameter is a multidimensional array, only the length array parameter, and the change is reflected in the of the first dimension may be omitted. corresponding argument. • If we revise sum_array so that a is a two-dimensional array, we must specify the number of columns in a: • A function that modifies an array by storing zero #define LEN 10 into each of its elements: int sum_two_dimensional_array(int a[][LEN], int n) void store_zeros(int a[], int n) { { int i, j, sum = 0; int i; for (i = 0; i < n; i++) for (i = 0; i < n; i++) for (j = 0; j < LEN; j++) sum += a[i][j]; a[i] = 0; return sum; } }

55 Copyright © 2008 W. W. Norton & Company. 57 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Array Arguments Variable-Length Array Parameters (C99) • Not being able to pass multidimensional arrays • Using a variable-length array parameter, we can with an arbitrary number of columns can be a explicitly state that a’s length is n: nuisance. int sum_array(int n, int a[n]) { • We can often work around this difficulty by using … arrays of pointers. } • C99’s variable-length array parameters provide an • The value of the first parameter (n) specifies the even better solution. length of the second parameter (a). • Note that the order of the parameters has been switched; order is important when variable-length array parameters are used.

58 Copyright © 2008 W. W. Norton & Company. 60 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Variable-Length Array Parameters (C99) Variable-Length Array Parameters (C99) • C99 allows the use of variable-length arrays as • There are several ways to write the prototype for parameters. the new version of sum_array. • Consider the sum_array function: • One possibility is to make it look exactly like the int sum_array(int a[], int n) function definition: { … int sum_array(int n, int a[n]); /* Version 1 */ } • Another possibility is to replace the array length by As it stands now, there’s no direct link between n and an asterisk (*): the length of the array a. int sum_array(int n, int a[*]); /* Version 2a */ • Although the function body treats n as a’s length, the actual length of the array could be larger or smaller than n.

59 Copyright © 2008 W. W. Norton & Company. 61 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Variable-Length Array Parameters (C99) Variable-Length Array Parameters (C99) • The reason for using the * notation is that • In general, the length of a variable-length array parameter parameter names are optional in function can be any expression. declarations. • A function that concatenates two arrays a and b, storing the result into a third array named c: • If the name of the first parameter is omitted, it int concatenate(int m, int n, int a[m], int b[n], wouldn’t be possible to specify that the length of int c[m+n]) the array is n, but the * provides a clue that the { … length of the array is related to parameters that } come earlier in the list: • The expression used to specify the length of c involves two int sum_array(int, int [*]); /* Version 2b */ other parameters, but in general it could refer to variables outside the function or even call other functions.

62 Copyright © 2008 W. W. Norton & Company. 64 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Variable-Length Array Parameters (C99) Variable-Length Array Parameters (C99) • It’s also legal to leave the brackets empty, as we • Variable-length array parameters with a single normally do when declaring an array parameter: dimension have limited usefulness. int sum_array(int n, int a[]); /* Version 3a */ • They make a function declaration or definition int sum_array(int, int []); /* Version 3b */ more descriptive by stating the desired length of • Leaving the brackets empty isn’t a good choice, an array argument. because it doesn’t expose the relationship between • However, no additional error-checking is n and a. performed; it’s still possible for an array argument to be too long or too short.

63 Copyright © 2008 W. W. Norton & Company. 65 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Using static in Array Parameter Variable-Length Array Parameters (C99) Declarations (C99) • Variable-length array parameters are most useful for • C99 allows the use of the keyword static in the multidimensional arrays. declaration of array parameters. • By using a variable-length array parameter, we can generalize the sum_two_dimensional_array • The following example uses static to indicate function to any number of columns: that the length of a is guaranteed to be at least 3: int sum_two_dimensional_array(int n, int m, int a[n][m]) int sum_array(int a[static 3], int n) { { int i, j, sum = 0; … for (i = 0; i < n; i++) } for (j = 0; j < m; j++) sum += a[i][j]; return sum; }

66 Copyright © 2008 W. W. Norton & Company. 68 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Using static in Array Parameter Variable-Length Array Parameters (C99) Declarations (C99) • Prototypes for this function include: • Using static has no effect on program int sum_two_dimensional_array(int n, int m, int a[n][m]); int sum_two_dimensional_array(int n, int m, int a[*][*]); behavior. int sum_two_dimensional_array(int n, int m, int a[][m]); • The presence of static is merely a “hint” that int sum_two_dimensional_array(int n, int m, int a[][*]); may allow a C compiler to generate faster instructions for accessing the array. • If an array parameter has more than one dimension, static can be used only in the first dimension.

67 Copyright © 2008 W. W. Norton & Company. 69 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Compound Literals (C99) Compound Literals (C99) • Let’s return to the original sum_array function. • A compound literal resembles a cast applied to an • When sum_array is called, the first argument is initializer. usually the name of an array. • In fact, compound literals and initializers obey the • Example: same rules. int b[] = {3, 0, 3, 4, 1}; • A compound literal may contain designators, just like total = sum_array(b, 5); a designated initializer, and it may fail to provide full •bmust be declared as a variable and then initialized initialization (in which case any uninitialized elements prior to the call. default to zero). • If b isn’t needed for any other purpose, it can be • For example, the literal (int [10]){8, 6} has 10 annoying to create it solely for the purpose of calling elements; the first two have the values 8 and 6, and the sum_array. remaining elements have the value 0.

70 Copyright © 2008 W. W. Norton & Company. 72 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Compound Literals (C99) Compound Literals (C99) • In C99, we can avoid this annoyance by using a compound • Compound literals created inside a function may literal: an unnamed array that’s created “on the fly” by contain arbitrary expressions, not just constants: simply specifying which elements it contains. total = sum_array((int []){2 * i, i + j, j * k}, 3); • A call of sum_array with a compound literal (shown in • A compound literal is an lvalue, so the values of bold) as its first argument: total = sum_array((int []){3, 0, 3, 4, 1}, 5); its elements can be changed. • We didn’t specify the length of the array, so it’s • If desired, a compound literal can be made “read- determined by the number of elements in the literal. only” by adding the word const to its type: • We also have the option of specifying a length explicitly: (const int []){5, 4} (int [4]){1, 9, 2, 1} is equivalent to (int []){1, 9, 2, 1}

71 Copyright © 2008 W. W. Norton & Company. 73 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions The return Statement The return Statement • A non-void function must use the return • return statements may appear in functions statement to specify what value it will return. whose return type is void, provided that no • The return statement has the form expression is given: return expression ; return; /* return in a void function */ • The expression is often just a constant or variable: • Example: return 0; void print_int(int i) return status; { if (i < 0) • More complex expressions are possible: return; return n >= 0 ? n : 0; printf("%d", i); }

74 Copyright © 2008 W. W. Norton & Company. 76 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions The return Statement The return Statement • If the type of the expression in a return • A return statement may appear at the end of a statement doesn’t match the function’s return type, void function: the expression will be implicitly converted to the void print_pun(void) { return type. printf("To C, or not to C: that is the question.\n"); – If a function returns an int, but the return statement return; /* OK, but not needed */ contains a double expression, the value of the } expression is converted to int. Using return here is unnecessary. • If a non-void function fails to execute a return statement, the behavior of the program is undefined if it attempts to use the function’s return value.

75 Copyright © 2008 W. W. Norton & Company. 77 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Program Termination Program Termination • Normally, the return type of main is int: • The value returned by main is a status code that int main(void) can be tested when the program terminates. { • main should return 0 if the program terminates … } normally. • Older C programs often omit main’s return type, • To indicate abnormal termination, main should taking advantage of the fact that it traditionally return a value other than 0. defaults to int: • It’s good practice to make sure that every C main() program returns a status code. { … }

78 Copyright © 2008 W. W. Norton & Company. 80 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Program Termination The exit Function • Omitting the return type of a function isn’t legal in • Executing a return statement in main is one C99, so it’s best to avoid this practice. way to terminate a program. • Omitting the word void in main’s parameter list • Another is calling the exit function, which remains legal, but—as a matter of style—it’s best belongs to . to include it. • The argument passed to exit has the same meaning as main’s return value: both indicate the program’s status at termination. • To indicate normal termination, we’d pass 0: exit(0); /* normal termination */

79 Copyright © 2008 W. W. Norton & Company. 81 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions The exit Function Recursion • Since 0 is a bit cryptic, C allows us to pass • A function is recursive if it calls itself. EXIT_SUCCESS instead (the effect is the same): • The following function computes n! recursively, exit(EXIT_SUCCESS); using the formula n! = n ×(n – 1)!: • Passing EXIT_FAILURE indicates abnormal int fact(int n) termination: { exit(EXIT_FAILURE); if (n <= 1) • EXIT_SUCCESS and EXIT_FAILURE are macros return 1; defined in . else return n * fact(n - 1); • The values of EXIT_SUCCESS and } EXIT_FAILURE are implementation-defined; typical values are 0 and 1, respectively.

82 Copyright © 2008 W. W. Norton & Company. 84 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions The exit Function Recursion • The statement • To see how recursion works, let’s trace the return expression; execution of the statement in main is equivalent to i = fact(3);

exit(expression); fact(3) finds that 3 is not less than or equal to 1, so it calls • The difference between return and exit is that fact(2), which finds that 2 is not less than or equal to 1, so exit causes program termination regardless of it calls which function calls it. fact(1), which finds that 1 is less than or equal to 1, so it returns 1, causing return • The statement causes program fact(2) to return 2 × 1 = 2, causing termination only when it appears in the main fact(3) to return 3 × 2 = 6. function.

83 Copyright © 2008 W. W. Norton & Company. 85 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions Recursion The Quicksort Algorithm • The following recursive function computes xn, • Recursion is most helpful for sophisticated using the formula xn = x × xn–1. algorithms that require a function to call itself two int power(int x, int n) or more times. { • Recursion often arises as a result of an algorithm if (n == 0) design technique known as divide-and-conquer, in return 1; else which a large problem is divided into smaller return x * power(x, n - 1); pieces that are then tackled by the same } algorithm.

86 Copyright © 2008 W. W. Norton & Company. 88 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions Recursion The Quicksort Algorithm • We can condense the power function by putting a • A classic example of divide-and-conquer can be conditional expression in the return statement: found in the popular Quicksort algorithm. int power(int x, int n) • Assume that the array to be sorted is indexed from { 1 to n. return n ==0?1:x*power(x, n - 1); } Quicksort algorithm fact power 1. Choose an array element e (the “partitioning element”), • Both and are careful to test a then rearrange the array so that elements 1, …, i – 1 are “termination condition” as soon as they’re called. less than or equal to e, element i contains e, and elements • All recursive functions need some kind of i + 1, …, n are greater than or equal to e. termination condition in order to prevent infinite 2. elements 1, …, i – 1 by using Quicksort recursively. recursion. 3. Sort elements i + 1, …, n by using Quicksort recursively.

87 Copyright © 2008 W. W. Norton & Company. 89 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions The Quicksort Algorithm The Quicksort Algorithm • Step 1 of the Quicksort algorithm is obviously • Example of partitioning an array: critical. • There are various methods to partition an array. • We’ll use a technique that’s easy to understand but not particularly efficient. • The algorithm relies on two “markers” named low and high, which keep track of positions within the array.

90 Copyright © 2008 W. W. Norton & Company. 92 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions The Quicksort Algorithm The Quicksort Algorithm • Initially, low points to the first element; high points to the last. • By the final figure, all elements to the left of the • We copy the first element (the partitioning element) into a partitioning element are less than or equal to 12, temporary location, leaving a “hole” in the array. and all elements to the right are greater than or • Next, we move high across the array from right to left until it equal to 12. points to an element that’s smaller than the partitioning element. • We then copy the element into the hole that low points to, • Now that the array has been partitioned, we can which creates a new hole (pointed to by high). use Quicksort recursively to sort the first four • We now move low from left to right, looking for an element elements of the array (10, 3, 6, and 7) and the last that’s larger than the partitioning element. When we one, two (15 and 18). we copy it into the hole that high points to. • The process repeats until low and high meet at a hole. • Finally, we copy the partitioning element into the hole.

91 Copyright © 2008 W. W. Norton & Company. 93 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 9: Functions

void quicksort(int a[], int low, int high) Program: Quicksort { int middle; • Let’s develop a recursive function named quicksort if (low >= high) return; middle = (a, low, high); that uses the Quicksort algorithm to sort an array of quicksort(a, low, middle - 1); integers. quicksort(a, middle + 1, high); } • The qsort.c program reads 10 numbers into an array, calls quicksort to sort the array, then prints the elements in the array: Enter 10 numbers to be sorted: 9 16 47 82 4 66 12 3 25 51 In sorted order: 3 4 9 12 16 25 47 51 66 82 • The code for partitioning the array is in a separate function named split.

94 Copyright © 2008 W. W. Norton & Company. 96 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 9: Functions Chapter 9: Functions

int split(int a[], int low, int high) qsort.c { int part_element = a[low]; /* Sorts an array of integers using Quicksort algorithm */ for (;;) { #include while (low < high && part_element <= a[high]) #define N 10 high--; void quicksort(int a[], int low, int high); if (low >= high) break; int split(int a[], int low, int high); a[low++] = a[high]; int main(void) while (low < high && a[low] <= part_element) { low++; int a[N], i; if (low >= high) break; printf("Enter %d numbers to be sorted: ", N); a[high--] = a[low]; for (i = 0; i < N; i++) } scanf("%d", &a[i]); a[high] = part_element; quicksort(a, 0, N - 1); return high; printf("In sorted order: "); } for (i = 0; i < N; i++) printf("%d ", a[i]); printf("\n"); return 0; }

95 Copyright © 2008 W. W. Norton & Company. 97 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 9: Functions Chapter 10: Program Organization Program: Quicksort Local Variables • Ways to improve the program’s performance: • A variable declared in the body of a function is – Improve the partitioning algorithm. said to be local to the function: – Use a different method to sort small arrays. int sum_digits(int n) – Make Quicksort nonrecursive. { int sum = 0; /* local variable */ while (n > 0) { sum += n % 10; n /= 10; } return sum; }

98 Copyright © 2008 W. W. Norton & Company. 2 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization Local Variables • Default properties of local variables: – Automatic storage duration. Storage is “automatically” allocated when the enclosing function is called and Chapter 10 deallocated when the function returns. – Block scope. A local variable is visible from its point of Program Organization declaration to the end of the enclosing function body.

1 Copyright © 2008 W. W. Norton & Company. 3 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization Local Variables Parameters • Since C99 doesn’t require variable declarations to • Parameters have the same properties—automatic come at the beginning of a function, it’s possible storage duration and block scope—as local for a local variable to have a very small scope: variables. • Each parameter is initialized automatically when a function is called (by being assigned the value of the corresponding argument).

4 Copyright © 2008 W. W. Norton & Company. 6 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization Static Local Variables External Variables • Including static in the declaration of a local variable • Passing arguments is one way to transmit causes it to have static storage duration. information to a function. • A variable with static storage duration has a permanent • Functions can also communicate through external storage location, so it retains its value throughout the variables—variables that are declared outside the execution of the program. body of any function. • Example: void f(void) • External variables are sometimes known as global { variables. static int i; /* static local variable */ … } • A static local variable still has block scope, so it’s not visible to other functions.

5 Copyright © 2008 W. W. Norton & Company. 7 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization Example: Using External Variables External Variables to Implement a Stack • Properties of external variables: • One way to implement a stack in C is to store its – Static storage duration items in an array, which we’ll call contents. – File scope • A separate integer variable named top marks the • Having file scope means that an external variable position of the stack top. is visible from its point of declaration to the end of – When the stack is empty, top has the value 0. the enclosing file. • To push an item: Store it in contents at the position indicated by top, then increment top. • To pop an item: Decrement top, then use it as an index into contents to fetch the item that’s being popped.

8 Copyright © 2008 W. W. Norton & Company. 10 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization Example: Using External Variables Example: Using External Variables to Implement a Stack to Implement a Stack • To illustrate how external variables might be used, • The following program fragment declares the let’s look at a data structure known as a stack. contents and top variables for a stack. • A stack, like an array, can store multiple data • It also provides a set of functions that represent items of the same type. stack operations. • The operations on a stack are limited: • All five functions need access to the top variable, – Push an item (add it to one end—the “stack top”) and two functions need access to contents, so – Pop an item (remove it from the same end) contents and top will be external. • Examining or modifying an item that’s not at the top of the stack is forbidden.

9 Copyright © 2008 W. W. Norton & Company. 11 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization Example: Using External Variables Pros and Cons of External Variables to Implement a Stack #include /* C99 only */ • External variables are convenient when many functions #define STACK_SIZE 100 must share a variable or when a few functions share a /* external variables */ large number of variables. int contents[STACK_SIZE]; int top = 0; • In most cases, it’s better for functions to communicate through parameters rather than by sharing variables: void make_empty(void) { – If we change an external variable during program maintenance top = 0; (by altering its type, say), we’ll need to check every function in } the same file to see how the change affects it. bool is_empty(void) – If an external variable is assigned an incorrect value, it may be { return top == 0; difficult to identify the guilty function. } – Functions that rely on external variables are hard to reuse in other programs.

12 Copyright © 2008 W. W. Norton & Company. 14 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization Example: Using External Variables Pros and Cons of External Variables to Implement a Stack bool is_full(void) • Don’t use the same external variable for different { return top == STACK_SIZE; } purposes in different functions. void push(int i) • Suppose that several functions need a variable { if (is_full() named i to control a for statement. stack_overflow(); • Instead of declaring i in each function that uses it, else contents[top++] = i; } some programmers declare it just once at the top of the program. int pop(void) { if (is_empty()) • This practice is misleading; someone reading the stack_underflow(); program later may think that the uses of i are else return contents[--top]; related, when in fact they’re not. }

13 Copyright © 2008 W. W. Norton & Company. 15 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization Pros and Cons of External Variables Program: Guessing a Number • Make sure that external variables have meaningful • The guess.c program generates a random number names. between 1 and 100, which the user attempts to guess • Local variables don’t always need meaningful in as few tries as possible: Guess the secret number between 1 and 100. names: it’s often hard to think of a better name than i for the control variable in a for loop. A new number has been chosen. Enter guess: 55 Too low; try again. Enter guess: 65 Too high; try again. Enter guess: 60 Too high; try again. Enter guess: 58 You won in 4 guesses!

16 Copyright © 2008 W. W. Norton & Company. 18 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization Pros and Cons of External Variables Program: Guessing a Number

• Making variables external when they should be local can lead to Play again? (Y/N) y some rather frustrating bugs. A new number has been chosen. • Code that is supposed to display a 10 × 10 arrangement of asterisks: Enter guess: 78 int i; Too high; try again. Enter guess: 34 void print_one_row(void) { You won in 2 guesses! for (i = 1; i <= 10; i++) printf("*"); Play again? (Y/N) n } • Tasks to be carried out by the program: void print_all_rows(void) { – Initialize the random number generator for (i = 1; i <= 10; i++) { print_one_row(); – Choose a secret number printf("\n"); } – Interact with the user until the correct number is picked } • Instead of printing 10 rows, print_all_rows prints only one. • Each task can be handled by a separate function.

17 Copyright © 2008 W. W. Norton & Company. 19 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization

/********************************************************** guess.c * initialize_number_generator: Initializes the random * /* Asks user to guess a hidden number */ * number generator using * * the time of day. * #include **********************************************************/ #include void initialize_number_generator(void) #include { srand((unsigned) time(NULL)); #define MAX_NUMBER 100 }

/* external variable */ /********************************************************** int secret_number; * choose_new_secret_number: Randomly selects a number * * between 1 and MAX_NUMBER and * /* prototypes */ * stores it in secret_number. * void initialize_number_generator(void); **********************************************************/ void choose_new_secret_number(void); void choose_new_secret_number(void) void read_guesses(void); { secret_number = rand() % MAX_NUMBER + 1; }

20 Copyright © 2008 W. W. Norton & Company. 22 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization int main(void) /********************************************************** { * read_guesses: Repeatedly reads user guesses and tells * * the user whether each guess is too low, * char command; * too high, or correct. When the guess is * printf("Guess the secret number between 1 and %d.\n\n", * correct, prints the total number of * MAX_NUMBER); * guesses and returns. * initialize_number_generator(); **********************************************************/ do { void read_guesses(void) choose_new_secret_number(); { int guess, num_guesses = 0; printf("A new number has been chosen.\n"); read_guesses(); for (;;) { printf("Play again? (Y/N) "); num_guesses++; scanf(" %c", &command); printf("Enter guess: "); scanf("%d", &guess); printf("\n"); if (guess == secret_number) { } while (command == 'y' || command == 'Y'); printf("You won in %d guesses!\n\n", num_guesses); return; return 0; } else if (guess < secret_number) } printf("Too low; try again.\n"); else printf("Too high; try again.\n"); } }

21 Copyright © 2008 W. W. Norton & Company. 23 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization

int main(void) Program: Guessing a Number { char command; • Although guess.c works fine, it relies on the int secret_number; external variable secret_number. printf("Guess the secret number between 1 and %d.\n\n", MAX_NUMBER); • By altering choose_new_secret_number initialize_number_generator(); and read_guesses slightly, we can move do { secret_number = new_secret_number(); secret_number into the main function. printf("A new number has been chosen.\n"); read_guesses(secret_number); • The new version of guess.c follows, with printf("Play again? (Y/N) "); scanf(" %c", &command); changes in bold. printf("\n"); } while (command == 'y' || command == 'Y');

return 0; }

24 Copyright © 2008 W. W. Norton & Company. 26 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization

/********************************************************** guess2.c * initialize_number_generator: Initializes the random * /* Asks user to guess a hidden number */ * number generator using * * the time of day. * #include **********************************************************/ #include void initialize_number_generator(void) #include { srand((unsigned) time(NULL)); #define MAX_NUMBER 100 }

/* prototypes */ /********************************************************** void initialize_number_generator(void); * new_secret_number: Returns a randomly chosen number * int new_secret_number(void); * between 1 and MAX_NUMBER. * void read_guesses(int secret_number); **********************************************************/ int new_secret_number(void) { return rand() % MAX_NUMBER + 1; }

25 Copyright © 2008 W. W. Norton & Company. 27 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization /********************************************************** * read_guesses: Repeatedly reads user guesses and tells * * the user whether each guess is too low, * Blocks * too high, or correct. When the guess is * * correct, prints the total number of * • Example of a block: * guesses and returns. * **********************************************************/ if (i > j) { void read_guesses(int secret_number) { /* swap values of i and j */ int guess, num_guesses = 0; int temp = i; for (;;) { i = j; num_guesses++; printf("Enter guess: "); j = temp; scanf("%d", &guess); } if (guess == secret_number) { printf("You won in %d guesses!\n\n", num_guesses); return; } else if (guess < secret_number) printf("Too low; try again.\n"); else printf("Too high; try again.\n"); } }

28 Copyright © 2008 W. W. Norton & Company. 30 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization Blocks Blocks • In Section 5.2, we encountered compound • By default, the storage duration of a variable statements of the form declared in a block is automatic: storage for the { statements } variable is allocated when the block is entered and • C allows compound statements to contain deallocated when the block is exited. declarations as well as statements: • The variable has block scope; it can’t be { declarations statements } referenced outside the block. • This kind of compound statement is called a • A variable that belongs to a block can be declared block. static to give it static storage duration.

29 Copyright © 2008 W. W. Norton & Company. 31 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization Blocks Scope • The body of a function is a block. • In the example on the next slide, the identifier i • Blocks are also useful inside a function body when has four different meanings: we need variables for temporary use. – In Declaration 1, i is a variable with static storage duration and file scope. • Advantages of declaring temporary variables in – In Declaration 2, i is a parameter with block scope. blocks: – In Declaration 3, i is an automatic variable with block – Avoids cluttering declarations at the beginning of the scope. function body with variables that are used only briefly. – In Declaration 4, i is also automatic and has block – Reduces name conflicts. scope. • C99 allows variables to be declared anywhere • C’s scope rules allow us to determine the meaning within a block. of i each time it’s used (indicated by arrows).

32 Copyright © 2008 W. W. Norton & Company. 34 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization Scope • In a C program, the same identifier may have several different meanings. • C’s scope rules enable the programmer (and the compiler) to determine which meaning is relevant at a given point in the program. • The most important scope rule: When a declaration inside a block names an identifier that’s already visible, the new declaration temporarily “hides” the old one, and the identifier takes on a new meaning. • At the end of the block, the identifier regains its old meaning.

33 Copyright © 2008 W. W. Norton & Company. 35 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization Organizing a C Program Organizing a C Program • Major elements of a C program: • There are several ways to organize a program so – Preprocessing directives such as #include and that these rules are obeyed. #define • One possible ordering: – Type definitions – #include directives – Declarations of external variables – #define directives – Function prototypes – Type definitions – Function definitions – Declarations of external variables – Prototypes for functions other than main – Definition of main – Definitions of other functions

36 Copyright © 2008 W. W. Norton & Company. 38 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization Organizing a C Program Organizing a C Program • C imposes only a few rules on the order of these • It’s a good idea to have a boxed comment items: preceding each function definition. – A preprocessing directive doesn’t take effect until the • Information to include in the comment: line on which it appears. – Name of the function – A type name can’t be used until it’s been defined. – Purpose of the function – A variable can’t be used until it’s declared. – Meaning of each parameter • It’s a good idea to define or declare every function – Description of return value (if any) prior to its first call. – Description of side effects (such as modifying external – C99 makes this a requirement. variables)

37 Copyright © 2008 W. W. Norton & Company. 39 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization Program: Classifying a Poker Hand Program: Classifying a Poker Hand • The poker.c program will classify a poker hand. • For input purposes, ranks and suits will be single • Each card in the hand has a suit and a rank. letters (upper- or lower-case): – Suits: clubs, diamonds, hearts, spades Ranks: 2 3 4 5 6 7 8 9 t j q k a – Ranks: two, three, four, five, six, seven, eight, nine, ten, Suits: c d h s jack, queen, king, ace • Actions to be taken if the user enters an illegal card or • Jokers are not allowed, and aces are high. tries to enter the same card twice: • After reading a hand of five cards, the program will – Ignore the card classify the hand using the categories on the next – Issue an error message slide. – Request another card • If a hand falls into two or more categories, the • Entering the number 0 instead of a card will cause the program will choose the best one. program to terminate.

40 Copyright © 2008 W. W. Norton & Company. 42 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization Program: Classifying a Poker Hand Program: Classifying a Poker Hand • Categories (listed from best to worst): • A sample session with the program: – straight flush (both a straight and a flush) Enter a card: 2s – four-of-a-kind (four cards of the same rank) Enter a card: 5s – full house (a three-of-a-kind and a pair) Enter a card: 4s – flush (five cards of the same suit) Enter a card: 3s – straight (five cards with consecutive ranks) Enter a card: 6s – three-of-a-kind (three cards of the same rank) Straight flush – two pairs – pair (two cards of the same rank) – high card (any other hand)

41 Copyright © 2008 W. W. Norton & Company. 43 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization Program: Classifying a Poker Hand Program: Classifying a Poker Hand Enter a card: 8c • The program has three tasks: Enter a card: as Enter a card: 8c – Read a hand of five cards Duplicate card; ignored. – Analyze the hand for pairs, straights, and so forth Enter a card: 7c – Print the classification of the hand Enter a card: ad • The functions read_cards, analyze_hand, Enter a card: 3h and print_result will perform these tasks. Pair • main does nothing but call these functions inside an endless loop.

44 Copyright © 2008 W. W. Norton & Company. 46 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization Program: Classifying a Poker Hand Program: Classifying a Poker Hand Enter a card: 6s • The functions will need to share a fairly large Enter a card: d2 amount of information, so we’ll have them Bad card; ignored. Enter a card: 2d communicate through external variables. Enter a card: 9c • read_cards will store information about the Enter a card: 4h hand into several external variables. Enter a card: ts • analyze_hand High card will then examine these variables, storing its findings into other external Enter a card: 0 variables for the benefit of print_result.

45 Copyright © 2008 W. W. Norton & Company. 47 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization Program: Classifying a Poker Hand Program: Classifying a Poker Hand /********************************************************** • Program outline: * analyze_hand: Determines whether the hand contains a * * straight, a flush, four-of-a-kind, * /* #include directives go here */ * and/or three-of-a-kind; determines the * * number of pairs; stores the results into * /* #define directives go here */ * external variables. * **********************************************************/ /* declarations of external variables go here */ void analyze_hand(void) { … /* prototypes */ } void read_cards(void); void analyze_hand(void); /********************************************************** * print_result: Notifies the user of the result, using * void print_result(void); * the external variables set by * * analyze_hand. * **********************************************************/ void print_result(void) { … }

48 Copyright © 2008 W. W. Norton & Company. 50 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization Program: Classifying a Poker Hand Program: Classifying a Poker Hand /********************************************************** * main: Calls read_cards, analyze_hand, and print_result * • How should we represent the hand of cards? * repeatedly. * **********************************************************/ • analyze_hand will need to know how many cards int main(void) { are in each rank and each suit. for (;;) { read_cards(); • This suggests that we use two arrays, num_in_rank analyze_hand(); and num_in_suit. print_result(); } – num_in_rank[r] will be the number of cards with rank r. } – num_in_suit[s] will be the number of cards with suit s. /********************************************************** * read_cards: Reads the cards into external variables; * • We’ll encode ranks as numbers between 0 and 12. * checks for bad cards and duplicate cards. * **********************************************************/ • Suits will be numbers between 0 and 3. void read_cards(void) { … }

49 Copyright © 2008 W. W. Norton & Company. 51 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization Program: Classifying a Poker Hand poker.c /* Classifies a poker hand */ • We’ll also need a third array, card_exists, so #include /* C99 only */ that read_cards can detect duplicate cards. #include • Each time read_cards reads a card with rank r #include and suit s, it checks whether the value of #define NUM_RANKS 13 #define NUM_SUITS 4 card_exists[r][s] is true. #define NUM_CARDS 5 – If so, the card was previously entered. /* external variables */ – If not, read_cards assigns true to int num_in_rank[NUM_RANKS]; card_exists[r][s]. int num_in_suit[NUM_SUITS]; bool straight, flush, four, three; int pairs; /* can be 0, 1, or 2 */

52 Copyright © 2008 W. W. Norton & Company. 54 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization

/* prototypes */ Program: Classifying a Poker Hand void read_cards(void); void analyze_hand(void); • Both the read_cards function and the void print_result(void); analyze_hand function will need access to the /********************************************************** * main: Calls read_cards, analyze_hand, and print_result * num_in_rank and num_in_suit arrays, so * repeatedly. * they will be external variables. **********************************************************/ int main(void) • The card_exists array is used only by { for (;;) { read_cards, so it can be local to that function. read_cards(); analyze_hand(); • As a rule, variables should be made external only print_result(); if necessary. } }

53 Copyright © 2008 W. W. Norton & Company. 55 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 10: Program Organization

/********************************************************** suit_ch = getchar(); * read_cards: Reads the cards into the external * switch (suit_ch) { * variables num_in_rank and num_in_suit; * case 'c': case 'C': suit = 0; break; * checks for bad cards and duplicate cards. * case 'd': case 'D': suit = 1; break; **********************************************************/ case 'h': case 'H': suit = 2; break; void read_cards(void) case 's': case 'S': suit = 3; break; { default: bad_card = true; bool card_exists[NUM_RANKS][NUM_SUITS]; } char ch, rank_ch, suit_ch; while ((ch = getchar()) != '\n') int rank, suit; if (ch != ' ') bad_card = true; bool bad_card; if (bad_card) int cards_read = 0; printf("Bad card; ignored.\n"); else if (card_exists[rank][suit]) for (rank = 0; rank < NUM_RANKS; rank++) { printf("Duplicate card; ignored.\n"); num_in_rank[rank] = 0; else { for (suit = 0; suit < NUM_SUITS; suit++) num_in_rank[rank]++; card_exists[rank][suit] = false; num_in_suit[suit]++; } card_exists[rank][suit] = true; cards_read++; for (suit = 0; suit < NUM_SUITS; suit++) } } num_in_suit[suit] = 0; }

56 Copyright © 2008 W. W. Norton & Company. 58 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 10: Program Organization

while (cards_read < NUM_CARDS) { /********************************************************** bad_card = false; * analyze_hand: Determines whether the hand contains a * printf("Enter a card: "); * straight, a flush, four-of-a-kind, * * and/or three-of-a-kind; determines the * rank_ch = getchar(); * number of pairs; stores the results into * switch (rank_ch) { * the external variables straight, flush, * case '0': exit(EXIT_SUCCESS); * four, three, and pairs. * case '2': rank = 0; break; case '3': rank = 1; break; **********************************************************/ case '4': rank = 2; break; void analyze_hand(void) case '5': rank = 3; break; { case '6': rank = 4; break; int num_consec = 0; case '7': rank = 5; break; int rank, suit; case '8': rank = 6; break; straight = false; case '9': rank = 7; break; flush = false; case 't': case 'T': rank = 8; break; four = false; case 'j': case 'J': rank = 9; break; three = false; case 'q': case 'Q': rank = 10; break; pairs = 0; case 'k': case 'K': rank = 11; break; case 'a': case 'A': rank = 12; break; default: bad_card = true; }

57 Copyright © 2008 W. W. Norton & Company. 59 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 10: Program Organization Chapter 11: Pointers

/* check for flush */ for (suit = 0; suit < NUM_SUITS; suit++) if (num_in_suit[suit] == NUM_CARDS) flush = true; /* check for straight */ rank = 0; while (num_in_rank[rank] == 0) rank++; for (; rank < NUM_RANKS && num_in_rank[rank] > 0; rank++) Chapter 11 num_consec++; if (num_consec == NUM_CARDS) { straight = true; return; Pointers } /* check for 4-of-a-kind, 3-of-a-kind, and pairs */ for (rank = 0; rank < NUM_RANKS; rank++) { if (num_in_rank[rank] == 4) four = true; if (num_in_rank[rank] == 3) three = true; if (num_in_rank[rank] == 2) pairs++; } }

60 Copyright © 2008 W. W. Norton & Company. 1 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 10: Program Organization Chapter 11: Pointers

/********************************************************** * print_result: Prints the classification of the hand, * Pointer Variables * based on the values of the external * * variables straight, flush, four, three, * * and pairs. * • The first step in understanding pointers is **********************************************************/ visualizing what they represent at the machine void print_result(void) { level. if (straight && flush) printf("Straight flush"); else if (four) printf("Four of a kind"); • In most modern computers, main memory is else if (three && divided into bytes, with each byte capable of pairs == 1) printf("Full house"); else if (flush) printf("Flush"); storing eight bits of information: else if (straight) printf("Straight"); else if (three) printf("Three of a kind"); else if (pairs == 2) printf("Two pairs"); else if (pairs == 1) printf("Pair"); else printf("High card"); • Each byte has a unique address. printf("\n\n"); }

61 Copyright © 2008 W. W. Norton & Company. 2 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 11: Pointers Chapter 11: Pointers Pointer Variables Pointer Variables • If there are n bytes in memory, we can think of • Addresses can be stored in special pointer addresses as numbers that range from 0 to n – 1: variables. • When we store the address of a variable i in the pointer variable p, we say that p “points to” i. • A graphical representation:

3 Copyright © 2008 W. W. Norton & Company. 5 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 11: Pointers Chapter 11: Pointers Pointer Variables Declaring Pointer Variables • Each variable in a program occupies one or more • When a pointer variable is declared, its name must bytes of memory. be preceded by an asterisk: • The address of the first byte is said to be the int *p; address of the variable. •pis a pointer variable capable of pointing to • In the following figure, the address of the variable objects of type int. i is 2000: • We use the term object instead of variable since p might point to an area of memory that doesn’t belong to a variable.

4 Copyright © 2008 W. W. Norton & Company. 6 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 11: Pointers Chapter 11: Pointers Declaring Pointer Variables The Address Operator • Pointer variables can appear in declarations along with • Declaring a pointer variable sets aside space for a other variables: pointer but doesn’t make it point to an object: int i, j, a[10], b[20], *p, *q; int *p; /* points nowhere in particular */ • C requires that every pointer variable point only to • It’s crucial to initialize p before we use it. objects of a particular type (the referenced type): int *p; /* points only to integers */ double *q; /* points only to doubles */ char *r; /* points only to characters */ • There are no restrictions on what the referenced type may be.

7 Copyright © 2008 W. W. Norton & Company. 9 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 11: Pointers Chapter 11: Pointers The Address and Indirection Operators The Address Operator • C provides a pair of operators designed • One way to initialize a pointer variable is to assign specifically for use with pointers. it the address of a variable: – To find the address of a variable, we use the & (address) int i, *p; operator. … – To gain access to the object that a pointer points to, we p = &i; use the * (indirection) operator. • Assigning the address of i to the variable p makes p point to i:

8 Copyright © 2008 W. W. Norton & Company. 10 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 11: Pointers Chapter 11: Pointers The Address Operator The Indirection Operator • It’s also possible to initialize a pointer variable at • As long as p points to i, *p is an for i. the time it’s declared: –*phas the same value as i. int i; – Changing the value of *p changes the value of i. int *p = &i; • The example on the next slide illustrates the • The declaration of i can even be combined with equivalence of *p and i. the declaration of p: int i, *p = &i;

11 Copyright © 2008 W. W. Norton & Company. 13 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 11: Pointers Chapter 11: Pointers The Indirection Operator The Indirection Operator • Once a pointer variable points to an object, we can p = &i; use the * (indirection) operator to access what’s stored in the object. i = 1; • If p points to i, we can print the value of i as follows: printf("%d\n", i); /* prints 1 */ printf("%d\n", *p); printf("%d\n", *p); /* prints 1 */ • Applying & to a variable produces a pointer to the *p = 2; variable. Applying * to the pointer takes us back to the original variable: printf("%d\n", i); /* prints 2 */ j = *&i; /* same as j = i; */ printf("%d\n", *p); /* prints 2 */

12 Copyright © 2008 W. W. Norton & Company. 14 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 11: Pointers Chapter 11: Pointers The Indirection Operator Pointer Assignment • Applying the indirection operator to an • Another example of pointer assignment: uninitialized pointer variable causes undefined q = p; behavior: q now points to the same place as p: int *p; printf("%d", *p); /*** WRONG ***/ • Assigning a value to *p is particularly dangerous: int *p; *p = 1; /*** WRONG ***/

15 Copyright © 2008 W. W. Norton & Company. 17 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 11: Pointers Chapter 11: Pointers Pointer Assignment Pointer Assignment • C allows the use of the assignment operator to • If p and q both point to i, we can change i by copy pointers of the same type. assigning a new value to either *p or *q: • Assume that the following declaration is in effect: *p = 1; int i, j, *p, *q; • Example of pointer assignment: p = &i; *q = 2;

• Any number of pointer variables may point to the same object. 16 Copyright © 2008 W. W. Norton & Company. 18 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 11: Pointers Chapter 11: Pointers Pointer Assignment Pointers as Arguments • Be careful not to confuse • In Chapter 9, we tried—and failed—to write a q = p; decompose function that could modify its with arguments. *q = *p; • By passing a pointer to a variable instead of the • The first statement is a pointer assignment, but the value of the variable, decompose can be fixed. second is not. • The example on the next slide shows the effect of the second statement.

19 Copyright © 2008 W. W. Norton & Company. 21 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 11: Pointers Chapter 11: Pointers Pointer Assignment Pointers as Arguments p = &i; • New definition of decompose: q = &j; void decompose(double x, long *int_part, i = 1; double *frac_part) { *int_part = (long) x; *frac_part = x - *int_part; } *q = *p; • Possible prototypes for decompose: void decompose(double x, long *int_part, double *frac_part); void decompose(double, long *, double *);

20 Copyright © 2008 W. W. Norton & Company. 22 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 11: Pointers Chapter 11: Pointers Pointers as Arguments Pointers as Arguments • A call of decompose: • The second assignment stores x - *int_part decompose(3.14159, &i, &d); into the object that frac_part points to: • As a result of the call, int_part points to i and frac_part points to d:

23 Copyright © 2008 W. W. Norton & Company. 25 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 11: Pointers Chapter 11: Pointers Pointers as Arguments Pointers as Arguments • The first assignment in the body of decompose • Arguments in calls of scanf are pointers: converts the value of x to type long and stores it int i; in the object pointed to by int_part: … scanf("%d", &i); Without the &, scanf would be supplied with the value of i.

24 Copyright © 2008 W. W. Norton & Company. 26 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 11: Pointers Chapter 11: Pointers Program: Finding the Largest and Pointers as Arguments Smallest Elements in an Array • Although scanf’s arguments must be pointers, • The max_min.c program uses a function named max_min it’s not always true that every argument needs the to find the largest and smallest elements in an array. & operator: • Prototype for max_min: int i, *p; void max_min(int a[], int n, int *max, int *min); … • Example call of max_min: p = &i; max_min(b, N, &big, &small); scanf("%d", p); • When max_min finds the largest element in b, it stores the • Using the & operator in the call would be wrong: value in big by assigning it to *max. scanf("%d", &p); /*** WRONG ***/ • max_min stores the smallest element of b in small by assigning it to *min.

27 Copyright © 2008 W. W. Norton & Company. 29 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 11: Pointers Chapter 11: Pointers Program: Finding the Largest and Pointers as Arguments Smallest Elements in an Array • Failing to pass a pointer to a function when one is expected • max_min.c will read 10 numbers into an array, pass can have disastrous results. it to the max_min function, and print the results: • A call of decompose in which the & operator is missing: Enter 10 numbers: 34 82 49 102 7 94 23 11 50 31 decompose(3.14159, i, d); Largest: 102 • When decompose stores values in *int_part and Smallest: 7 *frac_part, it will attempt to change unknown memory locations instead of modifying i and d. • If we’ve provided a prototype for decompose, the compiler will detect the error. • In the case of scanf, however, failing to pass pointers may go undetected.

28 Copyright © 2008 W. W. Norton & Company. 30 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 11: Pointers Chapter 11: Pointers maxmin.c Using const to Protect Arguments /* Finds the largest and smallest elements in an array */ • When an argument is a pointer to a variable x, we #include normally assume that x will be modified: #define N 10 f(&x); void max_min(int a[], int n, int *max, int *min); • It’s possible, though, that f merely needs to int main(void) examine the value of x, not change it. { int b[N], i, big, small; • The reason for the pointer might be efficiency: passing the value of a variable can waste time and printf("Enter %d numbers: ", N); for (i = 0; i < N; i++) space if the variable requires a large amount of scanf("%d", &b[i]); storage.

31 Copyright © 2008 W. W. Norton & Company. 33 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 11: Pointers Chapter 11: Pointers

max_min(b, N, &big, &small); Using const to Protect Arguments printf("Largest: %d\n", big); printf("Smallest: %d\n", small); • We can use const to document that a function return 0; won’t change an object whose address is passed to } the function. void max_min(int a[], int n, int *max, int *min) • const { goes in the parameter’s declaration, just int i; before the specification of its type:

*max = *min = a[0]; void f(const int *p) for (i = 1; i < n; i++) { { if (a[i] > *max) *p = 0; /*** WRONG ***/ *max = a[i]; else if (a[i] < *min) } *min = a[i]; } Attempting to modify *p is an error that the } compiler will detect.

32 Copyright © 2008 W. W. Norton & Company. 34 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 11: Pointers Chapter 11: Pointers Pointers as Return Values Pointers as Return Values • Functions are allowed to return pointers: • Pointers can point to array elements. int *max(int *a, int *b) • If a is an array, then &a[i] is a pointer to { if (*a > *b) element i of a. return a; • It’s sometimes useful for a function to return a else return b; pointer to one of the elements in an array. } • A function that returns a pointer to the middle • A call of the max function: element of a, assuming that a has n elements: int *p, i, j; … int *find_middle(int a[], int n) { p = max(&i, &j); return &a[n/2]; After the call, p points to either i or j. }

35 Copyright © 2008 W. W. Norton & Company. 37 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 11: Pointers Chapter 12: Pointers and Arrays Pointers as Return Values • Although max returns one of the pointers passed to it as an argument, that’s not the only possibility. • A function could also return a pointer to an external variable or to a static local variable. Chapter 12 • Never return a pointer to an automatic local variable: int *f(void) Pointers and Arrays { int i; … return &i; } The variable i won’t exist after f returns.

36 Copyright © 2008 W. W. Norton & Company. 1 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Introduction Pointer Arithmetic • C allows us to perform arithmetic—addition and • We can now access a[0] through p; for example, subtraction—on pointers to array elements. we can store the value 5 in a[0] by writing • This leads to an alternative way of processing *p = 5; arrays in which pointers take the place of array • An updated picture: subscripts. • The relationship between pointers and arrays in C is a close one. • Understanding this relationship is critical for mastering C.

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Pointer Arithmetic Pointer Arithmetic • Chapter 11 showed that pointers can point to array • If p points to an element of an array a, the other elements: elements of a can be accessed by performing int a[10], *p; pointer arithmetic (or address arithmetic) on p. p = &a[0]; • C supports three (and only three) forms of pointer • A graphical representation: arithmetic: – Adding an integer to a pointer – Subtracting an integer from a pointer – Subtracting one pointer from another

3 Copyright © 2008 W. W. Norton & Company. 5 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Adding an Integer to a Pointer Subtracting an Integer from a Pointer • Adding an integer j to a pointer p yields a pointer • If p points to a[i], then p-jpoints to a[i-j]. to the element j places after the one that p points • Example: to. p = &a[8]; • More precisely, if p points to the array element a[i], then p+jpoints to a[i+j]. • Assume that the following declarations are in q = p - 3; effect: int a[10], *p, *q, i;

p -= 6;

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Adding an Integer to a Pointer Subtracting One Pointer from Another • Example of pointer addition: • When one pointer is subtracted from another, the result p = &a[2]; is the distance (measured in array elements) between the pointers. • If p points to a[i] and q points to a[j], then p-qis equal to i-j. q = p + 3; • Example: p = &a[5]; q = &a[1];

p += 6;

i = p - q; /* i is 4 */ i = q - p; /* i is -4 */

7 Copyright © 2008 W. W. Norton & Company. 9 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Subtracting One Pointer from Another Pointers to Compound Literals (C99) • Operations that cause undefined behavior: • It’s legal for a pointer to point to an element – Performing arithmetic on a pointer that doesn’t point to within an array created by a compound literal: an array element int *p = (int []){3, 0, 3, 4, 1}; – Subtracting pointers unless both point to elements of • Using a compound literal saves us the trouble of the same array first declaring an array variable and then making p point to the first element of that array: int a[] = {3, 0, 3, 4, 1}; int *p = &a[0];

10 Copyright © 2008 W. W. Norton & Company. 12 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Comparing Pointers Using Pointers for Array Processing • Pointers can be compared using the relational • Pointer arithmetic allows us to visit the elements operators (<, <=, >, >=) and the equality operators of an array by repeatedly incrementing a pointer (== and !=). variable. – Using relational operators is meaningful only for pointers to • A loop that sums the elements of an array a: elements of the same array. #define N 10 • The outcome of the comparison depends on the … relative positions of the two elements in the array. int a[N], sum, *p; • After the assignments … p = &a[5]; sum = 0; q = &a[1]; for (p = &a[0]; p < &a[N]; p++) the value of p<=qis 0 and the value of p>=qis 1. sum += *p;

11 Copyright © 2008 W. W. Norton & Company. 13 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Using Pointers for Array Processing Combining the * and ++ Operators At the end of the first iteration: • C programmers often combine the * (indirection) and ++ operators. • A statement that modifies an array element and then advances to the next element: At the end of the second iteration: a[i++] = j; • The corresponding pointer version: *p++ = j; At the end of the third iteration: • Because the postfix version of ++ takes precedence over *, the compiler sees this as *(p++) = j;

14 Copyright © 2008 W. W. Norton & Company. 16 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Using Pointers for Array Processing Combining the * and ++ Operators • The condition p < &a[N] in the for statement • Possible combinations of * and ++: deserves special mention. Expression Meaning • It’s legal to apply the address operator to a[N], *p++ or *(p++) Value of expression is *p before increment; increment p later even though this element doesn’t exist. (*p)++ Value of expression is *p before increment; • Pointer arithmetic may save execution time. increment *p later • However, some C compilers produce better code *++p or *(++p) Increment p first; for loops that rely on subscripting. value of expression is *p after increment ++*p or ++(*p) Increment *p first; value of expression is *p after increment

15 Copyright © 2008 W. W. Norton & Company. 17 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Combining the * and ++ Operators Combining the * and ++ Operators • The most common combination of * and ++ is • The new push and pop functions: *p++, which is handy in loops. void push(int i) { • Instead of writing if (is_full()) stack_overflow(); for (p = &a[0]; p < &a[N]; p++) else sum += *p; *top_ptr++ = i; } to sum the elements of the array a, we could write int pop(void) p = &a[0]; { while (p < &a[N]) if (is_empty()) sum += *p++; stack_underflow(); else return *--top_ptr; }

18 Copyright © 2008 W. W. Norton & Company. 20 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Combining the * and ++ Operators Using an Array Name as a Pointer • The * and -- operators mix in the same way as * • Pointer arithmetic is one way in which arrays and and ++. pointers are related. • For an application that combines * and --, let’s • Another key relationship: return to the stack example of Chapter 10. The name of an array can be used as a pointer to • The original version of the stack relied on an the first element in the array. integer variable named top to keep track of the • This relationship simplifies pointer arithmetic and “top-of-stack” position in the contents array. makes both arrays and pointers more versatile. • Let’s replace top by a pointer variable that points initially to element 0 of the contents array: int *top_ptr = &contents[0];

19 Copyright © 2008 W. W. Norton & Company. 21 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Using an Array Name as a Pointer Using an Array Name as a Pointer • Suppose that a is declared as follows: • Although an array name can be used as a pointer, int a[10]; it’s not possible to assign it a new value. • Examples of using a as a pointer: • Attempting to make it point elsewhere is an error: *a = 7; /* stores 7 in a[0] */ while (*a != 0) *(a+1) = 12; /* stores 12 in a[1] */ a++; /*** WRONG ***/ • In general, a+iis the same as &a[i]. • This is no great loss; we can always copy a into a – Both represent a pointer to element i of a. pointer variable, then change the pointer variable: • Also, *(a+i) is equivalent to a[i]. p = a; while (*p != 0) – Both represent element i itself. p++;

22 Copyright © 2008 W. W. Norton & Company. 24 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Program: Reversing a Series Using an Array Name as a Pointer of Numbers (Revisited) • The fact that an array name can serve as a pointer • The reverse.c program of Chapter 8 reads 10 makes it easier to write loops that step through an numbers, then writes the numbers in reverse order. array. • The original program stores the numbers in an • Original loop: array, with subscripting used to access elements of for (p = &a[0]; p < &a[N]; p++) the array. sum += *p; • reverse3.c is a new version of the program in • Simplified version: which subscripting has been replaced with pointer for (p = a; p < a + N; p++) arithmetic. sum += *p;

23 Copyright © 2008 W. W. Norton & Company. 25 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays reverse3.c Array Arguments (Revisited) /* Reverses a series of numbers (pointer version) */ #include • The fact that an array argument is treated as a #define N 10 pointer has some important consequences. int main(void) • Consequence 1: When an ordinary variable is { int a[N], *p; passed to a function, its value is copied; any printf("Enter %d numbers: ", N); changes to the corresponding parameter don’t for (p = a; p < a + N; p++) affect the variable. scanf("%d", p); printf("In reverse order:"); • In contrast, an array used as an argument isn’t for (p = a + N - 1; p >= a; p--) protected against change. printf(" %d", *p); printf("\n"); return 0; }

26 Copyright © 2008 W. W. Norton & Company. 28 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Array Arguments (Revisited) Array Arguments (Revisited) • When passed to a function, an array name is treated as a pointer. • For example, the following function modifies an • Example: array by storing zero into each of its elements: int find_largest(int a[], int n) { void store_zeros(int a[], int n) int i, max; { max = a[0]; int i; for (i = 1; i < n; i++) if (a[i] > max) max = a[i]; for (i = 0; i < n; i++) return max; a[i] = 0; } } • A call of find_largest: largest = find_largest(b, N); This call causes a pointer to the first element of b to be assigned to a; the array itself isn’t copied.

27 Copyright © 2008 W. W. Norton & Company. 29 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Array Arguments (Revisited) Array Arguments (Revisited) • To indicate that an array parameter won’t be • Consequence 3: An array parameter can be changed, we can include the word const in its declared as a pointer if desired. declaration: • find_largest could be defined as follows: int find_largest(const int a[], int n) int find_largest(int *a, int n) { { … … } } • If const is present, the compiler will check that • Declaring a to be a pointer is equivalent to no assignment to an element of a appears in the declaring it to be an array; the compiler treats the body of find_largest. declarations as though they were identical.

30 Copyright © 2008 W. W. Norton & Company. 32 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Array Arguments (Revisited) Array Arguments (Revisited) • Consequence 2: The time required to pass an array • Although declaring a parameter to be an array is to a function doesn’t depend on the size of the the same as declaring it to be a pointer, the same array. isn’t true for a variable. • There’s no penalty for passing a large array, since • The following declaration causes the compiler to no copy of the array is made. set aside space for 10 integers: int a[10]; • The following declaration causes the compiler to allocate space for a pointer variable: int *a;

31 Copyright © 2008 W. W. Norton & Company. 33 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Array Arguments (Revisited) Using a Pointer as an Array Name • In the latter case, a is not an array; attempting to • C allows us to subscript a pointer as though it use it as an array can have disastrous results. were an array name: • For example, the assignment #define N 10 *a = 0; /*** WRONG ***/ … int a[N], i, sum = 0, *p = a; will store 0 where a is pointing. … • Since we don’t know where a is pointing, the for (i = 0; i < N; i++) effect on the program is undefined. sum += p[i]; The compiler treats p[i] as *(p+i).

34 Copyright © 2008 W. W. Norton & Company. 36 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Array Arguments (Revisited) Pointers and Multidimensional Arrays • Consequence 4: A function with an array • Just as pointers can point to elements of one- parameter can be passed an array “slice”—a dimensional arrays, they can also point to sequence of consecutive elements. elements of multidimensional arrays. • An example that applies find_largest to • This section explores common techniques for elements 5 through 14 of an array b: using pointers to process the elements of largest = find_largest(&b[5], 10); multidimensional arrays.

35 Copyright © 2008 W. W. Norton & Company. 37 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Processing the Elements Processing the Elements of a Multidimensional Array of a Multidimensional Array • Chapter 8 showed that C stores two-dimensional • Although treating a two-dimensional array as one- arrays in row-major order. dimensional may seem like cheating, it works with • Layout of an array with r rows: most C compilers. • Techniques like this one definitely hurt program readability, but—at least with some older compilers—produce a compensating increase in efficiency. • If p initially points to the element in row 0, column 0, we can visit every element in the array by • With many modern compilers, though, there’s incrementing p repeatedly. often little or no speed advantage.

38 Copyright © 2008 W. W. Norton & Company. 40 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Processing the Elements Processing the Rows of a Multidimensional Array of a Multidimensional Array • Consider the problem of initializing all elements of the following • A pointer variable p can also be used for array to zero: processing the elements in just one row of a two- int a[NUM_ROWS][NUM_COLS]; • The obvious technique would be to use nested for loops: dimensional array. int row, col; • To visit the elements of row i, we’d initialize p to … for (row = 0; row < NUM_ROWS; row++) point to element 0 in row i in the array a: for (col = 0; col < NUM_COLS; col++) p = &a[i][0]; a[row][col] = 0; • If we view a as a one-dimensional array of integers, a single loop or we could simply write is sufficient: p = a[i]; int *p; … for (p = &a[0][0]; p <= &a[NUM_ROWS-1][NUM_COLS-1]; p++) *p = 0;

39 Copyright © 2008 W. W. Norton & Company. 41 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Processing the Rows Processing the Rows of a Multidimensional Array of a Multidimensional Array • For any two-dimensional array a, the expression • Consider find_largest, which was originally a[i] is a pointer to the first element in row i. designed to find the largest element of a one- • To see why this works, recall that a[i] is dimensional array. equivalent to *(a + i). • We can just as easily use find_largest to • Thus, &a[i][0] is the same as &(*(a[i] + 0)), determine the largest element in row i of the two- which is equivalent to &*a[i]. dimensional array a: • This is the same as a[i], since the & and * largest = find_largest(a[i], NUM_COLS); operators cancel.

42 Copyright © 2008 W. W. Norton & Company. 44 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Processing the Rows Processing the Columns of a Multidimensional Array of a Multidimensional Array • A loop that clears row i of the array a: • Processing the elements in a column of a two- int a[NUM_ROWS][NUM_COLS], *p, i; dimensional array isn’t as easy, because arrays are … stored by row, not by column. for (p = a[i]; p < a[i] + NUM_COLS; p++) *p = 0; • A loop that clears column i of the array a: • Since a[i] is a pointer to row i of the array a, we int a[NUM_ROWS][NUM_COLS], (*p)[NUM_COLS], i; … can pass a[i] to a function that’s expecting a one- for (p = &a[0]; p < &a[NUM_ROWS]; p++) dimensional array as its argument. (*p)[i] = 0; • In other words, a function that’s designed to work with one-dimensional arrays will also work with a row belonging to a two-dimensional array.

43 Copyright © 2008 W. W. Norton & Company. 45 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Using the Name of a Using the Name of a Multidimensional Array as a Pointer Multidimensional Array as a Pointer • The name of any array can be used as a pointer, regardless • We can “trick” a function into thinking that a of how many dimensions it has, but some care is required. multidimensional array is really one-dimensional. • Example: • A first attempt at using using find_largest to find the int a[NUM_ROWS][NUM_COLS]; largest element in a: largest = find_largest(a, NUM_ROWS * NUM_COLS); a is not a pointer to a[0][0]; instead, it’s a pointer to /* WRONG */ a[0]. This an error, because the type of a is int (*)[NUM_COLS] • C regards a as a one-dimensional array whose elements are but find_largest is expecting an argument of type int *. one-dimensional arrays. • The correct call: • When used as a pointer, a has type int (*)[NUM_COLS] largest = find_largest(a[0], NUM_ROWS * NUM_COLS); (pointer to an integer array of length NUM_COLS). a[0] points to element 0 in row 0, and it has type int * (after conversion by the compiler).

46 Copyright © 2008 W. W. Norton & Company. 48 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Using the Name of a Pointers and Variable-Length Arrays (C99) Multidimensional Array as a Pointer • Knowing that a points to a[0] is useful for • Pointers are allowed to point to elements of simplifying loops that process the elements of a variable-length arrays (VLAs). two-dimensional array. • An ordinary pointer variable would be used to • Instead of writing point to an element of a one-dimensional VLA: for (p = &a[0]; p < &a[NUM_ROWS]; p++) void f(int n) (*p)[i] = 0; { int a[n], *p; to clear column i of the array a, we can write p = a; for (p = a; p < a + NUM_ROWS; p++) … (*p)[i] = 0; }

47 Copyright © 2008 W. W. Norton & Company. 49 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Pointers and Variable-Length Arrays (C99) Pointers and Variable-Length Arrays (C99) • When the VLA has more than one dimension, the • Variably modified types are subject to certain type of the pointer depends on the length of each restrictions. dimension except for the first. • The most important restriction: the declaration of • A two-dimensional example: a variably modified type must be inside the body void f(int m, int n) of a function or in a function prototype. { int a[m][n], (*p)[n]; p = a; … } Since the type of p depends on n, which isn’t constant, p is said to have a variably modified type.

50 Copyright © 2008 W. W. Norton & Company. 52 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 12: Pointers and Arrays Chapter 12: Pointers and Arrays Pointers and Variable-Length Arrays (C99) Pointers and Variable-Length Arrays (C99) • The validity of an assignment such as p=acan’t • Pointer arithmetic works with VLAs. always be determined by the compiler. • A two-dimensional VLA: • The following code will compile but is correct int a[m][n]; only if m and n are equal: • A pointer capable of pointing to a row of a: int a[m][n], (*p)[m]; int (*p)[n]; p = a; • A loop that clears column i of a: • If m is not equal to n, any subsequent use of p will for (p = a; p < a + m; p++) cause undefined behavior. (*p)[i] = 0;

51 Copyright © 2008 W. W. Norton & Company. 53 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings String Literals

• A string literal is a sequence of characters enclosed within double quotes: "When you come to a fork in the road, take it." Chapter 13 • String literals may contain escape sequences. • Character escapes often appear in printf and scanf format strings. Strings • For example, each \n character in the string "Candy\nIs dandy\nBut liquor\nIs quicker.\n --Ogden Nash\n" causes the cursor to advance to the next line: Candy Is dandy But liquor Is quicker. --Ogden Nash

1 Copyright © 2008 W. W. Norton & Company. 3 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Introduction Continuing a String Literal • This chapter covers both string constants (or • The backslash character (\) can be used to literals, as they’re called in the C standard) and continue a string literal from one line to the next: string variables. printf("When you come to a fork in the road, take it. \ --Yogi Berra"); • Strings are arrays of characters in which a special • In general, the \ character can be used to two character—the null character—marks the end. or more lines of a program into a single line. • The C library provides a collection of functions for working with strings.

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Continuing a String Literal How String Literals Are Stored • There’s a better way to deal with long string • The string literal "abc" is stored as an array of literals. four characters: • When two or more string literals are adjacent, the compiler will join them into a single string. • This rule allows us to split a string literal over two • The string "" is stored as a single null character: or more lines: printf("When you come to a fork in the road, take it. " "--Yogi Berra");

5 Copyright © 2008 W. W. Norton & Company. 7 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings How String Literals Are Stored How String Literals Are Stored • When a C compiler encounters a string literal of • Since a string literal is stored as an array, the length n in a program, it sets aside n + 1 bytes of compiler treats it as a pointer of type char *. memory for the string. • Both printf and scanf expect a value of type • This memory will contain the characters in the char * as their first argument. string, plus one extra character—the null • The following call of printf passes the address character—to mark the end of the string. of "abc" (a pointer to where the letter a is stored • The null character is a byte whose bits are all zero, in memory): so it’s represented by the \0 escape sequence. printf("abc");

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Operations on String Literals Operations on String Literals • We can use a string literal wherever C allows a • Attempting to modify a string literal causes char * pointer: undefined behavior: char *p; char *p = "abc"; p = "abc"; *p = 'd'; /*** WRONG ***/ • This assignment makes p point to the first • A program that tries to change a string literal may character of the string. crash or behave erratically.

9 Copyright © 2008 W. W. Norton & Company. 11 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Operations on String Literals String Literals versus Character Constants • String literals can be subscripted: • A string literal containing a single character isn’t char ch; the same as a character constant. ch = "abc"[1]; – "a" is represented by a pointer. – 'a' The new value of ch will be the letter b. is represented by an integer. • A legal call of printf: • A function that converts a number between 0 and 15 into the equivalent hex digit: printf("\n"); char digit_to_hex_char(int digit) • An illegal call: { printf('\n'); /*** WRONG ***/ return "0123456789ABCDEF"[digit]; }

10 Copyright © 2008 W. W. Norton & Company. 12 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings String Variables String Variables • Any one-dimensional array of characters can be • Be sure to leave room for the null character when used to store a string. declaring a string variable. • A string must be terminated by a null character. • Failing to do so may cause unpredictable results • Difficulties with this approach: when the program is executed. – It can be hard to tell whether an array of characters is • The actual length of a string depends on the being used as a string. position of the terminating null character. – String-handling functions must be careful to deal • An array of STR_LEN + 1 characters can hold properly with the null character. strings with lengths between 0 and STR_LEN. – Finding the length of a string requires searching for the null character.

13 Copyright © 2008 W. W. Norton & Company. 15 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings String Variables Initializing a String Variable • If a string variable needs to hold 80 characters, it • A string variable can be initialized at the same must be declared to have length 81: time it’s declared: #define STR_LEN 80 char date1[8] = "June 14"; … • The compiler will automatically add a null char str[STR_LEN+1]; character so that date1 can be used as a string: • Adding 1 to the desired length allows room for the null character at the end of the string. • Defining a macro that represents 80 and then • "June 14" is not a string literal in this context. adding 1 separately is a common practice. • Instead, C views it as an abbreviation for an array initializer.

14 Copyright © 2008 W. W. Norton & Company. 16 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Initializing a String Variable Initializing a String Variable • If the initializer is too short to fill the string • The declaration of a string variable may omit its variable, the compiler adds extra null characters: length, in which case the compiler computes it: char date2[9] = "June 14"; char date4[] = "June 14"; Appearance of date2: • The compiler sets aside eight characters for date4, enough to store the characters in "June 14" plus a null character. • Omitting the length of a string variable is especially useful if the initializer is long, since computing the length by hand is error-prone.

17 Copyright © 2008 W. W. Norton & Company. 19 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Initializing a String Variable Character Arrays versus Character Pointers • An initializer for a string variable can’t be longer • The declaration than the variable, but it can be the same length: char date[] = "June 14"; char date3[7] = "June 14"; declares date to be an array, • There’s no room for the null character, so the • The similar-looking compiler makes no attempt to store one: char *date = "June 14"; declares date to be a pointer. • Thanks to the close relationship between arrays and pointers, either version can be used as a string.

18 Copyright © 2008 W. W. Norton & Company. 20 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Character Arrays versus Character Pointers Character Arrays versus Character Pointers • However, there are significant differences between • Using an uninitialized pointer variable as a string the two versions of date. is a serious error. – In the array version, the characters stored in date can • An attempt at building the string "abc": be modified. In the pointer version, date points to a char *p; string literal that shouldn’t be modified. – In the array version, date is an array name. In the p[0] = 'a'; /*** WRONG ***/ pointer version, date is a variable that can point to p[1] = 'b'; /*** WRONG ***/ other strings. p[2] = 'c'; /*** WRONG ***/ p[3] = '\0'; /*** WRONG ***/ • Since p hasn’t been initialized, this causes undefined behavior.

21 Copyright © 2008 W. W. Norton & Company. 23 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Character Arrays versus Character Pointers Reading and Writing Strings • The declaration • Writing a string is easy using either printf or char *p; puts. does not allocate space for a string. • Reading a string is a bit harder, because the input • Before we can use p as a string, it must point to an may be longer than the string variable into which array of characters. it’s being stored. • One possibility is to make p point to a string variable: • To read a string in a single step, we can use either char str[STR_LEN+1], *p; scanf or gets. p = str; • As an alternative, we can read strings one • Another possibility is to make p point to a character at a time. dynamically allocated string.

22 Copyright © 2008 W. W. Norton & Company. 24 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Writing Strings Using printf and puts Writing Strings Using printf and puts • The %s conversion specification allows printf • The %ms conversion will display a string in a field to write a string: of size m. char str[] = "Are we having fun yet?"; • If the string has fewer than m characters, it will be printf("%s\n", str); right-justified within the field. The output will be • To force left justification instead, we can put a Are we having fun yet? minus sign in front of m. • printf writes the characters in a string one by • The m and p values can be used in combination. one until it encounters a null character. • A conversion specification of the form %m. causes the first p characters of a string to be displayed in a field of size m.

25 Copyright © 2008 W. W. Norton & Company. 27 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Writing Strings Using printf and puts Writing Strings Using printf and puts • To print part of a string, use the conversion • printf isn’t the only function that can write specification %.ps. strings. • p is the number of characters to be displayed. • The C library also provides puts: • The statement puts(str); printf("%.6s\n", str); • After writing a string, puts always writes an will print additional new-line character. Are we

26 Copyright © 2008 W. W. Norton & Company. 28 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Reading Strings Using scanf and gets Reading Strings Using scanf and gets • The %s conversion specification allows scanf to • Consider the following program fragment: read a string into a character array: char sentence[SENT_LEN+1]; scanf("%s", str); printf("Enter a sentence:\n"); • str is treated as a pointer, so there’s no need to scanf("%s", sentence); put the & operator in front of str. • Suppose that after the prompt • When scanf is called, it skips white space, then Enter a sentence: reads characters and stores them in str until it the user enters the line encounters a white-space character. To C, or not to C: that is the question. • scanf always stores a null character at the end of • scanf will store the string "To" in sentence. the string.

29 Copyright © 2008 W. W. Norton & Company. 31 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Reading Strings Using scanf and gets Reading Strings Using scanf and gets • scanf won’t usually read a full line of input. • Suppose that we replace scanf by gets: • A new-line character will cause scanf to stop gets(sentence); reading, but so will a space or tab character. • When the user enters the same input as before, • To read an entire line of input, we can use gets. gets will store the string • Properties of gets: " To C, or not to C: that is the question." – Doesn’t skip white space before starting to read input. in sentence. – Reads until it finds a new-line character. – Discards the new-line character instead of storing it; the null character takes its place.

30 Copyright © 2008 W. W. Norton & Company. 32 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Reading Strings Using scanf and gets Reading Strings Character by Character • As they read characters into an array, scanf and • Suppose we need a function that (1) doesn’t skip gets have no way to detect when it’s full. white-space characters, (2) stops reading at the first • Consequently, they may store characters past the new-line character (which isn’t stored in the string), and (3) discards extra characters. end of the array, causing undefined behavior. • A prototype for the function: • scanf can be made safer by using the conversion int read_line(char str[], int n); specification %ns instead of %s. • If the input line contains more than n characters, • n is an integer indicating the maximum number of read_line will discard the additional characters. characters to be stored. • read_line will return the number of characters it • gets is inherently unsafe; fgets is a much stores in str. better alternative.

33 Copyright © 2008 W. W. Norton & Company. 35 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Reading Strings Character by Character Reading Strings Character by Character • Programmers often write their own input functions. • read_line consists primarily of a loop that calls getchar to read a character and then stores the character • Issues to consider: in str, provided that there’s room left: – Should the function skip white space before beginning int read_line(char str[], int n) to store the string? { int ch, i = 0; – What character causes the function to stop reading: a new-line character, any white-space character, or some while ((ch = getchar()) != '\n') if (i < n) other character? Is this character stored in the string or str[i++] = ch; discarded? str[i] = '\0'; /* terminates string */ return i; /* number of characters stored */ – What should the function do if the input string is too } long to store: discard the extra characters or leave them •chhas int type rather than char type because for the next input operation? getchar returns an int value.

34 Copyright © 2008 W. W. Norton & Company. 36 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Reading Strings Character by Character Accessing the Characters in a String • Before returning, read_line puts a null • A function that counts the number of spaces in a character at the end of the string. string: • Standard functions such as scanf and gets int count_spaces(const char s[]) automatically put a null character at the end of an { input string. int count = 0, i; • If we’re writing our own input function, we must for (i = 0; s[i] != '\0'; i++) take on that responsibility. if (s[i] == ' ') count++; return count; }

37 Copyright © 2008 W. W. Norton & Company. 39 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Accessing the Characters in a String Accessing the Characters in a String • Since strings are stored as arrays, we can use • A version that uses pointer arithmetic instead of subscripting to access the characters in a string. array subscripting : • To process every character in a string s, we can int count_spaces(const char *s) set up a loop that increments a counter i and { selects characters via the expression s[i]. int count = 0; for (; *s != '\0'; s++) if (*s == ' ') count++; return count; }

38 Copyright © 2008 W. W. Norton & Company. 40 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Accessing the Characters in a String Using the C String Library • Questions raised by the count_spaces • Direct attempts to copy or compare strings will fail. example: • Copying a string into a character array using the = – Is it better to use array operations or pointer operator is not possible: operations to access the characters in a string? We can char str1[10], str2[10]; use either or both. Traditionally, C programmers lean … toward using pointer operations. str1 = "abc"; /*** WRONG ***/ – Should a string parameter be declared as an array or str2 = str1; /*** WRONG ***/ as a pointer? There’s no difference between the two. Using an array name as the left operand of = is illegal. – Does the form of the parameter (s[] or *s) affect • Initializing a character array using = is legal, though: what can be supplied as an argument? No. char str1[10] = "abc"; In this context, = is not the assignment operator.

41 Copyright © 2008 W. W. Norton & Company. 43 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Using the C String Library Using the C String Library • Some programming languages provide operators • Attempting to compare strings using a relational that can copy strings, compare strings, concatenate or equality operator is legal but won’t produce the strings, select substrings, and the like. desired result: • C’s operators, in contrast, are essentially useless if (str1 == str2) … /*** WRONG ***/ for working with strings. • This statement compares str1 and str2 as • Strings are treated as arrays in C, so they’re pointers. restricted in the same ways as arrays. • Since str1 and str2 have different addresses, • In particular, they can’t be copied or compared the expression str1 == str2 must have the using operators. value 0.

42 Copyright © 2008 W. W. Norton & Company. 44 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Using the C String Library The strcpy (String Copy) Function • The C library provides a rich set of functions for • A call of strcpy that stores the string "abcd" performing operations on strings. in str2: • Programs that need string operations should strcpy(str2, "abcd"); contain the following line: /* str2 now contains "abcd" */ #include • A call that copies the contents of str2 into • In subsequent examples, assume that str1 and str1: str2 are character arrays used as strings. strcpy(str1, str2); /* str1 now contains "abcd" */

45 Copyright © 2008 W. W. Norton & Company. 47 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings The strcpy (String Copy) Function The strcpy (String Copy) Function • Prototype for the strcpy function: • In the call strcpy(str1, str2), strcpy has char *strcpy(char *s1, const char *s2); no way to check that the str2 string will fit in the • strcpy copies the string s2 into the string s1. array pointed to by str1. – To be precise, we should say “strcpy copies the • If it doesn’t, undefined behavior occurs. string pointed to by s2 into the array pointed to by s1.” • strcpy returns s1 (a pointer to the destination string).

46 Copyright © 2008 W. W. Norton & Company. 48 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings The strcpy (String Copy) Function The strlen (String Length) Function • Calling the strncpy function is a safer, albeit • Prototype for the strlen function: slower, way to copy a string. size_t strlen(const char *s); • strncpy has a third argument that limits the • size_t is a typedef name that represents one number of characters that will be copied. of C’s unsigned integer types. • A call of strncpy that copies str2 into str1: strncpy(str1, str2, sizeof(str1));

49 Copyright © 2008 W. W. Norton & Company. 51 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings The strcpy (String Copy) Function The strlen (String Length) Function • strncpy will leave str1 without a terminating • strlen returns the length of a string s, not null character if the length of str2 is greater than including the null character. or equal to the size of the str1 array. • Examples: • A safer way to use strncpy: int len; strncpy(str1, str2, sizeof(str1) - 1); len = strlen("abc"); /* len is now 3 */ str1[sizeof(str1)-1] = '\0'; len = strlen(""); /* len is now 0 */ • The second statement guarantees that str1 is strcpy(str1, "abc"); always null-terminated. len = strlen(str1); /* len is now 3 */

50 Copyright © 2008 W. W. Norton & Company. 52 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings The strcat (String Concatenation) Function The strcat (String Concatenation) Function • Prototype for the strcat function: • strcat(str1, str2) causes undefined char *strcat(char *s1, const char *s2); behavior if the str1 array isn’t long enough to • strcat appends the contents of the string s2 to the end of accommodate the characters from str2. the string s1. • Example: • It returns s1 (a pointer to the resulting string). char str1[6] = "abc"; • strcat examples: strcpy(str1, "abc"); strcat(str1, "def"); /*** WRONG ***/ strcat(str1, "def"); /* str1 now contains "abcdef" */ • str1 is limited to six characters, causing strcpy(str1, "abc"); strcat to write past the end of the array. strcpy(str2, "def"); strcat(str1, str2); /* str1 now contains "abcdef" */

53 Copyright © 2008 W. W. Norton & Company. 55 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings The strcat (String Concatenation) Function The strcat (String Concatenation) Function • As with strcpy, the value returned by strcat • The strncat function is a safer but slower is normally discarded. version of strcat. • The following example shows how the return • Like strncpy, it has a third argument that limits value might be used: the number of characters it will copy. strcpy(str1, "abc"); • A call of strncat: strcpy(str2, "def"); strncat(str1, str2, sizeof(str1) - strlen(str1) - 1); strcat(str1, strcat(str2, "ghi")); • strncat str1 /* str1 now contains "abcdefghi"; will terminate with a null str2 contains "defghi" */ character, which isn’t included in the third argument.

54 Copyright © 2008 W. W. Norton & Company. 56 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings The strcmp (String Comparison) Function The strcmp (String Comparison) Function • Prototype for the strcmp function: • strcmp considers s1 to be less than s2 if either int strcmp(const char *s1, const char *s2); one of the following conditions is satisfied: • strcmp compares the strings s1 and s2, – The first i characters of s1 and s2 match, but the returning a value less than, equal to, or greater (i+1)st character of s1 is less than the (i+1)st character than 0, depending on whether s1 is less than, of s2. equal to, or greater than s2. – All characters of s1 match s2, but s1 is shorter than s2.

57 Copyright © 2008 W. W. Norton & Company. 59 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings The strcmp (String Comparison) Function The strcmp (String Comparison) Function • Testing whether str1 is less than str2: • As it compares two strings, strcmp looks at the if (strcmp(str1, str2) < 0) /* is str1 < str2? */ numerical codes for the characters in the strings. … • Some knowledge of the underlying character set is • Testing whether str1 is less than or equal to helpful to predict what strcmp will do. str2: • Important properties of ASCII: if (strcmp(str1, str2) <= 0) /* is str1 <= str2? */ … – A–Z, a–z, and 0–9 have consecutive codes. • By choosing the proper operator (<, <=, >, >=, – All upper-case letters are less than all lower-case ==, !=), we can test any possible relationship letters. between str1 and str2. – Digits are less than letters. – Spaces are less than all printing characters.

58 Copyright © 2008 W. W. Norton & Company. 60 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings

Program: Printing a One-Month Reminder List Program: Printing a One-Month Reminder List • The remind.c program prints a one-month list • Overall strategy: of daily reminders. – Read a series of day-and-reminder combinations. • The user will enter a series of reminders, with – Store them in order (sorted by day). each prefixed by a day of the month. – Display them. • When the user enters 0 instead of a valid day, the • scanf will be used to read the days. program will print a list of all reminders entered, • read_line will be used to read the reminders. sorted by day. • The next slide shows a session with the program.

61 Copyright © 2008 W. W. Norton & Company. 63 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings

Program: Printing a One-Month Reminder List Program: Printing a One-Month Reminder List Enter day and reminder: 24 Susan's birthday Enter day and reminder: 5 6:00 - Dinner with Marge and Russ • The strings will be stored in a two-dimensional Enter day and reminder: 26 Movie - "Chinatown" array of characters. Enter day and reminder: 7 10:30 - Dental appointment Enter day and reminder: 12 Movie - "Dazed and Confused" • Each row of the array contains one string. Enter day and reminder: 5 Saturday class Enter day and reminder: 12 Saturday class • Actions taken after the program reads a day and its Enter day and reminder: 0 associated reminder: Day Reminder – Search the array to determine where the day belongs, 5 Saturday class 5 6:00 - Dinner with Marge and Russ using strcmp to do comparisons. 7 10:30 - Dental appointment – Use strcpy to move all strings below that point down 12 Saturday class 12 Movie - "Dazed and Confused“ one position. 24 Susan's birthday – Copy the day into the array and call strcat to append 26 Movie - "Chinatown" the reminder to the day.

62 Copyright © 2008 W. W. Norton & Company. 64 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings

Program: Printing a One-Month Reminder List remind.c /* Prints a one-month reminder list */

• One complication: how to right-justify the days in #include a two-character field. #include scanf #define MAX_REMIND 50 /* maximum number of reminders */ • A solution: use to read the day into an #define MSG_LEN 60 /* max length of reminder message */ integer variable, than call sprintf to convert the int read_line(char str[], int n); day back into string form. int main(void) { • sprintf is similar to printf, except that it char reminders[MAX_REMIND][MSG_LEN+3]; char day_str[3], msg_str[MSG_LEN+1]; writes output into a string. int day, i, j, num_remind = 0; • The call for (;;) { if (num_remind == MAX_REMIND) { sprintf(day_str, "%2d", day); printf("-- No space left --\n"); break; writes the value of day into day_str. }

65 Copyright © 2008 W. W. Norton & Company. 67 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings printf("Enter day and reminder: "); Program: Printing a One-Month Reminder List scanf("%2d", &day); if (day == 0) break; • The following call of scanf ensures that the user sprintf(day_str, "%2d", day); doesn’t enter more than two digits: read_line(msg_str, MSG_LEN); for (i = 0; i < num_remind; i++) scanf("%2d", &day); if (strcmp(day_str, reminders[i]) < 0) break; for (j = num_remind; j > i; j--) strcpy(reminders[j], reminders[j-1]); strcpy(reminders[i], day_str); strcat(reminders[i], msg_str); num_remind++; } printf("\nDay Reminder\n"); for (i = 0; i < num_remind; i++) printf(" %s\n", reminders[i]); return 0; }

66 Copyright © 2008 W. W. Norton & Company. 68 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings int read_line(char str[], int n) { Searching for the End of a String int ch, i = 0; while ((ch = getchar()) != '\n') • A version of strlen that searches for the end of if (i < n) str[i++] = ch; a string, using a variable to keep track of the str[i] = '\0'; return i; string’s length: } size_t strlen(const char *s) { size_t n; for (n = 0; *s != '\0'; s++) n++; return n; }

69 Copyright © 2008 W. W. Norton & Company. 71 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings String Idioms Searching for the End of a String • Functions that manipulate strings are a rich source • To condense the function, we can move the of idioms. initialization of n to its declaration: • We’ll explore some of the most famous idioms by size_t strlen(const char *s) using them to write the strlen and strcat { functions. size_t n = 0; for (; *s != '\0'; s++) n++; return n; }

70 Copyright © 2008 W. W. Norton & Company. 72 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Searching for the End of a String Searching for the End of a String • The condition *s != '\0' is the same as *s != 0, • Replacing the for statement with a while which in turn is the same as *s. statement gives the following version of strlen: • A version of strlen that uses these observations: size_t strlen(const char *s) size_t strlen(const char *s) { { size_t n = 0; size_t n = 0; while (*s++) for (; *s; s++) n++; n++; return n; return n; } }

73 Copyright © 2008 W. W. Norton & Company. 75 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Searching for the End of a String Searching for the End of a String • The next version increments s and tests *s in the • Although we’ve condensed strlen quite a bit, same expression: it’s likely that we haven’t increased its speed. size_t strlen(const char *s) • A version that does run faster, at least with some { compilers: size_t n = 0; size_t strlen(const char *s) for (; *s++;) { n++; const char *p = s; return n; while (*s) } s++; return s - p; }

74 Copyright © 2008 W. W. Norton & Company. 76 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Searching for the End of a String Copying a String • Idioms for “search for the null character at the end char *strcat(char *s1, const char *s2) { of a string”: char *p = s1; while (*s) while (*s++) while (*p != '\0') s++; ; p++; • The first version leaves s pointing to the null while (*s2 != '\0') { character. *p = *s2; p++; • The second version is more concise, but leaves s s2++; pointing just past the null character. } *p = '\0'; return s1; }

77 Copyright © 2008 W. W. Norton & Company. 79 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Copying a String Copying a String • Copying a string is another common operation. •pinitially points to the first character in the s1 • To introduce C’s “string copy” idiom, we’ll string: develop two versions of the strcat function. • The first version of strcat (next slide) uses a two-step algorithm: – Locate the null character at the end of the string s1 and make p point to it. – Copy characters one by one from s2 to where p is pointing.

78 Copyright © 2008 W. W. Norton & Company. 80 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Copying a String Copying a String • The first while statement locates the null • The loop terminates when s2 points to the null character at the end of s1 and makes p point to it: character:

• After putting a null character where p is pointing, strcat returns.

81 Copyright © 2008 W. W. Norton & Company. 83 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Copying a String Copying a String • The second while statement repeatedly copies • Condensed version of strcat: one character from where s2 points to where p char *strcat(char *s1, const char *s2) points, then increments both p and s2. { • Assume that s2 originally points to the string char *p = s1; "def". while (*p) • The strings after the first loop iteration: p++; while (*p++ = *s2++) ; return s1; }

82 Copyright © 2008 W. W. Norton & Company. 84 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Copying a String Arrays of Strings • The heart of the streamlined strcat function is • There is more than one way to store an array of the “string copy” idiom: strings. while (*p++ = *s2++) • One option is to use a two-dimensional array of ; characters, with one string per row: • Ignoring the two ++ operators, the expression char planets[][8] = {"Mercury", "Venus", "Earth", inside the parentheses is an assignment: "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"}; *p = *s2 • The number of rows in the array can be omitted, • After the assignment, p and s2 are incremented. but we must specify the number of columns. • Repeatedly evaluating this expression copies characters from where s2 points to where p points.

85 Copyright © 2008 W. W. Norton & Company. 87 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Copying a String Arrays of Strings • But what causes the loop to terminate? • Unfortunately, the planets array contains a fair • The while statement tests the character that was bit of wasted space (extra null characters): copied by the assignment *p = *s2. • All characters except the null character test true. • The loop terminates after the assignment, so the null character will be copied.

86 Copyright © 2008 W. W. Norton & Company. 88 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Arrays of Strings Arrays of Strings • Most collections of strings will have a mixture of • To access one of the planet names, all we need do long strings and short strings. is subscript the planets array. • What we need is a ragged array, whose rows can • Accessing a character in a planet name is done in have different lengths. the same way as accessing an element of a two- • We can simulate a ragged array in C by creating dimensional array. an array whose elements are pointers to strings: • A loop that searches the planets array for char *planets[] = {"Mercury", "Venus", "Earth", strings beginning with the letter M: "Mars", "Jupiter", "Saturn", for (i = 0; i < 9; i++) "Uranus", "Neptune", "Pluto"}; if (planets[i][0] == 'M') printf("%s begins with M\n", planets[i]);

89 Copyright © 2008 W. W. Norton & Company. 91 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Arrays of Strings Command-Line Arguments • This small change has a dramatic effect on how • When we run a program, we’ll often need to planets is stored: supply it with information. • This may include a file name or a switch that modifies the program’s behavior. • Examples of the UNIX command: ls ls –l ls -l remind.c

90 Copyright © 2008 W. W. Norton & Company. 92 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Command-Line Arguments Command-Line Arguments • Command-line information is available to all • If the user enters the command line programs, not just operating system commands. ls -l remind.c • To obtain access to command-line arguments, then argc will be 3, and argv will have the main must have two parameters: following appearance: int main(int argc, char *argv[]) { … } • Command-line arguments are called program parameters in the C standard.

93 Copyright © 2008 W. W. Norton & Company. 95 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings Command-Line Arguments Command-Line Arguments • argc (“argument count”) is the number of • Since argv is an array of pointers, accessing command-line arguments. command-line arguments is easy. • argv (“argument vector”) is an array of pointers • Typically, a program that expects command-line to the command-line arguments (stored as strings). arguments will set up a loop that examines each • argv[0] points to the name of the program, argument in turn. while argv[1] through argv[argc-1] point • One way to write such a loop is to use an integer to the remaining command-line arguments. variable as an index into the argv array: • argv[argc] is always a null pointer—a special int i; pointer that points to nothing. for (i = 1; i < argc; i++) – The macro NULL represents a null pointer. printf("%s\n", argv[i]);

94 Copyright © 2008 W. W. Norton & Company. 96 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 13: Strings Chapter 13: Strings Command-Line Arguments planet.c /* Checks planet names */ • Another technique is to set up a pointer to #include argv[1], then increment the pointer repeatedly: #include char **p; #define NUM_PLANETS 9

for (p = &argv[1]; *p != NULL; p++) int main(int argc, char *argv[]) printf("%s\n", *p); { char *planets[] = {"Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"}; int i, j;

97 Copyright © 2008 W. W. Norton & Company. 99 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 13: Strings Chapter 13: Strings

for (i = 1; i < argc; i++) { Program: Checking Planet Names for (j = 0; j < NUM_PLANETS; j++) if (strcmp(argv[i], planets[j]) == 0) { • The planet.c program illustrates how to access printf("%s is planet %d\n", argv[i], j + 1); break; command-line arguments. } • The program is designed to check a series of strings to if (j == NUM_PLANETS) printf("%s is not a planet\n", argv[i]); see which ones are names of planets. }

• The strings are put on the command line: return 0; planet Jupiter venus Earth fred } • The program will indicate whether each string is a planet name and, if it is, display the planet’s number: Jupiter is planet 5 venus is not a planet Earth is planet 3 fred is not a planet

98 Copyright © 2008 W. W. Norton & Company. 100 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor How the Preprocessor Works • The preprocessor looks for preprocessing directives, which begin with a # character. • We’ve encountered the #define and #include Chapter 14 directives before. • #define defines a macro—a name that represents The Preprocessor something else, such as a constant. • The preprocessor responds to a #define directive by storing the name of the macro along with its definition. • When the macro is used later, the preprocessor “expands” the macro, replacing it by its defined value.

1 Copyright © 2008 W. W. Norton & Company. 3 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Introduction How the Preprocessor Works • Directives such as #define and #include are • #include tells the preprocessor to open a handled by the preprocessor, a piece of software particular file and “include” its contents as part of that edits C programs just prior to compilation. the file being compiled. • Its reliance on a preprocessor makes C (along with • For example, the line C++) unique among major programming #include languages. instructs the preprocessor to open the file named • The preprocessor is a powerful tool, but it also can stdio.h and bring its contents into the program. be a source of hard-to-find bugs.

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor How the Preprocessor Works How the Preprocessor Works • The preprocessor’s role in the compilation • The celsius.c program of Chapter 2: process: /* Converts a Fahrenheit temperature to Celsius */ #include #define FREEZING_PT 32.0f #define SCALE_FACTOR (5.0f / 9.0f) int main(void) { float fahrenheit, celsius; printf("Enter Fahrenheit temperature: "); scanf("%f", &fahrenheit); celsius = (fahrenheit - FREEZING_PT) * SCALE_FACTOR; printf("Celsius equivalent is: %.1f\n", celsius); return 0; }

5 Copyright © 2008 W. W. Norton & Company. 7 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor How the Preprocessor Works How the Preprocessor Works • The input to the preprocessor is a C program, • The program after preprocessing: Blank line possibly containing directives. Blank line Lines brought in from stdio.h • The preprocessor executes these directives, Blank line Blank line removing them in the process. Blank line Blank line • The preprocessor’s output goes directly into the int main(void) { compiler. float fahrenheit, celsius; printf("Enter Fahrenheit temperature: "); scanf("%f", &fahrenheit); celsius = (fahrenheit - 32.0f) * (5.0f / 9.0f); printf("Celsius equivalent is: %.1f\n", celsius); return 0; }

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor How the Preprocessor Works How the Preprocessor Works • The preprocessor does a bit more than just execute • Most C compilers provide a way to view the directives. output of the preprocessor. • In particular, it replaces each comment with a • Some compilers generate preprocessor output single space character. when a certain option is specified (GCC will do so • Some preprocessors go further and remove when the -E option is used). unnecessary white-space characters, including • Others come with a separate program that behaves spaces and tabs at the beginning of indented lines. like the integrated preprocessor.

9 Copyright © 2008 W. W. Norton & Company. 11 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor How the Preprocessor Works How the Preprocessor Works • In the early days of C, the preprocessor was a • A word of caution: The preprocessor has only a separate program. limited knowledge of C. • Nowadays, the preprocessor is often part of the • As a result, it’s quite capable of creating illegal compiler, and some of its output may not programs as it executes directives. necessarily be C code. • In complicated programs, examining the output of • Still, it’s useful to think of the preprocessor as the preprocessor may prove useful for locating this separate from the compiler. kind of error.

10 Copyright © 2008 W. W. Norton & Company. 12 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Preprocessing Directives Preprocessing Directives • Most preprocessing directives fall into one of • Directives always end at the first new-line three categories: character, unless explicitly continued. – Macro definition. The #define directive defines a To continue a directive to the next line, end the macro; the #undef directive removes a macro current line with a \ character: definition. #define DISK_CAPACITY (SIDES * \ – File inclusion. The #include directive causes the TRACKS_PER_SIDE * \ contents of a specified file to be included in a program. SECTORS_PER_TRACK * \ – Conditional compilation. The #if, #ifdef, BYTES_PER_SECTOR) #ifndef, #elif, #else, and #endif directives allow blocks of text to be either included in or excluded from a program.

13 Copyright © 2008 W. W. Norton & Company. 15 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Preprocessing Directives Preprocessing Directives • Several rules apply to all directives. • Directives can appear anywhere in a program. • Directives always begin with the # symbol. Although #define and #include directives The # symbol need not be at the beginning of a usually appear at the beginning of a file, other line, as long as only white space precedes it. directives are more likely to show up later. • Any number of spaces and horizontal tab • Comments may appear on the same line as a characters may separate the tokens in a directive. directive. Example: It’s good practice to put a comment at the end of # define N 100 a macro definition: #define FREEZING_PT 32.0f /* freezing point of water */

14 Copyright © 2008 W. W. Norton & Company. 16 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Macro Definitions Simple Macros • The macros that we’ve been using since Chapter 2 • Any extra symbols in a macro definition will are known as simple macros, because they have no become part of the replacement list. parameters. • Putting the = symbol in a macro definition is a • The preprocessor also supports parameterized common error: macros. #define N = 100 /*** WRONG ***/ … int a[N]; /* becomes int a[= 100]; */

17 Copyright © 2008 W. W. Norton & Company. 19 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Simple Macros Simple Macros • Definition of a simple macro (or object-like • Ending a macro definition with a semicolon is macro): another popular mistake: #define identifier replacement-list #define N 100; /*** WRONG ***/ replacement-list is any sequence of preprocessing … int a[N]; /* becomes int a[100;]; */ tokens. • The compiler will detect most errors caused by • The replacement list may include identifiers, extra symbols in a macro definition. keywords, numeric constants, character constants, string literals, operators, and punctuation. • Unfortunately, the compiler will flag each use of the macro as incorrect, rather than identifying the • Wherever identifier appears later in the file, the actual culprit: the macro’s definition. preprocessor substitutes replacement-list.

18 Copyright © 2008 W. W. Norton & Company. 20 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Simple Macros Simple Macros • Simple macros are primarily used for defining • Simple macros have additional uses. “manifest constants”—names that represent • Making minor changes to the syntax of C numeric, character, and string values: Macros can serve as alternate names for C #define STR_LEN 80 symbols: #define TRUE 1 #define FALSE 0 #define BEGIN { #define PI 3.14159 #define END } #define CR '\r' #define LOOP for (;;) #define EOS '\0' Changing the syntax of C usually isn’t a good #define MEM_ERR "Error: not enough memory" idea, since it can make programs harder for others to understand.

21 Copyright © 2008 W. W. Norton & Company. 23 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Simple Macros Simple Macros • Advantages of using #define to create names • Renaming types for constants: An example from Chapter 5: – It makes programs easier to read. The name of the #define BOOL int macro can help the reader understand the meaning of the constant. Type definitions are a better alternative. – It makes programs easier to modify. We can change • Controlling conditional compilation the value of a constant throughout a program by Macros play an important role in controlling modifying a single macro definition. conditional compilation. – It helps avoid inconsistencies and typographical errors. If a numerical constant like 3.14159 appears A macro that might indicate “debugging mode”: many times in a program, chances are it will #define DEBUG occasionally be written 3.1416 or 3.14195 by accident.

22 Copyright © 2008 W. W. Norton & Company. 24 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Simple Macros Parameterized Macros • When macros are used as constants, C • When the preprocessor encounters the definition programmers customarily capitalize all letters in of a parameterized macro, it stores the definition their names. away for later use. • However, there’s no consensus as to how to • Wherever a macro invocation of the form capitalize macros used for other purposes. identifier(y1, y2, …, yn) appears later in the – Some programmers like to draw attention to macros by program, the preprocessor replaces it with using all upper-case letters in their names. replacement-list, substituting y1 for x1, y2 for x2, – Others prefer lower-case names, following the style of and so forth. K&R. • Parameterized macros often serve as simple functions.

25 Copyright © 2008 W. W. Norton & Company. 27 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Parameterized Macros Parameterized Macros • Definition of a parameterized macro (also known as a • Examples of parameterized macros: function-like macro): #define MAX(x,y) ((x)>(y)?(x):(y))

#define identifier( x1 , x2 , … , xn ) replacement-list #define IS_EVEN(n) ((n)%2==0)

x1, x2, …, xn are identifiers (the macro’s parameters). • Invocations of these macros: • The parameters may appear as many times as desired i = MAX(j+k, m-n); in the replacement list. if (IS_EVEN(i)) i++; • There must be no space between the macro name and • The same lines after macro replacement: the left parenthesis. i = ((j+k)>(m-n)?(j+k):(m-n));

• If space is left, the preprocessor will treat (x1, x2, …, if (((i)%2==0)) i++; xn) as part of the replacement list.

26 Copyright © 2008 W. W. Norton & Company. 28 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Parameterized Macros Parameterized Macros • A more complicated function-like macro: • Parameterized macros also have disadvantages. #define TOUPPER(c) \ • The compiled code will often be larger. ('a'<=(c)&&(c)<='z'?(c)-'a'+'A':(c)) Each macro invocation increases the size of the • The header provides a similar source program (and hence the compiled code). function named toupper that’s more portable. The problem is compounded when macro • A parameterized macro may have an empty invocations are nested: parameter list: n = MAX(i, MAX(j, k)); #define getchar() getc(stdin) The statement after preprocessing: • The empty parameter list isn’t really needed, but it n = ((i)>(((j)>(k)?(j):(k)))?(i):(((j)>(k)?(j):(k)))); makes getchar resemble a function.

29 Copyright © 2008 W. W. Norton & Company. 31 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Parameterized Macros Parameterized Macros • Using a parameterized macro instead of a true • Arguments aren’t type-checked. function has a couple of advantages: When a function is called, the compiler checks – The program may be slightly faster. A function call each argument to see if it has the appropriate type. usually requires some overhead during program execution, but a macro invocation does not. Macro arguments aren’t checked by the preprocessor, nor are they converted. – Macros are “generic.” A macro can accept arguments of any type, provided that the resulting program is • It’s not possible to have a pointer to a macro. valid. C allows pointers to functions, a useful concept. Macros are removed during preprocessing, so there’s no corresponding notion of “pointer to a macro.”

30 Copyright © 2008 W. W. Norton & Company. 32 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Parameterized Macros Parameterized Macros • A macro may evaluate its arguments more than • Parameterized macros can be used as patterns for once. segments of code that are often repeated. Unexpected behavior may occur if an argument • A macro that makes it easier to display integers: has side effects: #define PRINT_INT(n) printf("%d\n", n) n = MAX(i++, j); • The preprocessor will turn the line The same line after preprocessing: PRINT_INT(i/j); n = ((i++)>(j)?(i++):(j)); into If i is larger than j, then i will be (incorrectly) printf("%d\n", i/j); incremented twice and n will be assigned an unexpected value.

33 Copyright © 2008 W. W. Norton & Company. 35 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Parameterized Macros The # Operator • Errors caused by evaluating a macro argument • Macro definitions may contain two special more than once can be difficult to find, because a operators, # and ##. macro invocation looks the same as a function • Neither operator is recognized by the compiler; call. instead, they’re executed during preprocessing. • To make matters worse, a macro may work • The # operator converts a macro argument into a properly most of the time, failing only for certain string literal; it can appear only in the replacement arguments that have side effects. list of a parameterized macro. • For self-protection, it’s a good idea to avoid side • The operation performed by # is known as effects in arguments. “stringization.”

34 Copyright © 2008 W. W. Norton & Company. 36 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor The # Operator The ## Operator • There are a number of uses for #; let’s consider • The ## operator can “” two tokens together just one. to form a single token. • Suppose that we decide to use the PRINT_INT • If one of the operands is a macro parameter, macro during debugging as a convenient way to pasting occurs after the parameter has been print the values of integer variables and replaced by the corresponding argument. expressions. • The # operator makes it possible for PRINT_INT to label each value that it prints.

37 Copyright © 2008 W. W. Norton & Company. 39 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor The # Operator The ## Operator • Our new version of PRINT_INT: • A macro that uses the ## operator: #define PRINT_INT(n) printf(#n " = %d\n", n) #define MK_ID(n) i##n • The invocation • A declaration that invokes MK_ID three times: PRINT_INT(i/j); int MK_ID(1), MK_ID(2), MK_ID(3); will become • The declaration after preprocessing: printf("i/j" " = %d\n", i/j); int i1, i2, i3; • The compiler automatically joins adjacent string literals, so this statement is equivalent to printf("i/j = %d\n", i/j);

38 Copyright © 2008 W. W. Norton & Company. 40 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor The ## Operator General Properties of Macros • The ## operator has a variety of uses. • Several rules apply to both simple and parameterized • Consider the problem of defining a max function macros. that behaves like the MAX macro described earlier. • A macro’s replacement list may contain invocations of other macros. • A single max function usually isn’t enough, because it will only work for arguments of one Example: type. #define PI 3.14159 #define TWO_PI (2*PI) • Instead, we can write a macro that expands into When it encounters TWO_PI later in the program, the the definition of a max function. preprocessor replaces it by (2*PI). • The macro’s parameter will specify the type of the The preprocessor then rescans the replacement list to arguments and the return value. see if it contains invocations of other macros.

41 Copyright © 2008 W. W. Norton & Company. 43 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor The ## Operator General Properties of Macros • There’s just one snag: if we use the macro to create more • The preprocessor replaces only entire tokens. than one function named max, the program won’t compile. Macro names embedded in identifiers, character • To solve this problem, we’ll use the ## operator to create a constants, and string literals are ignored. different name for each version of max: Example: #define GENERIC_MAX(type) \ type type##_max(type x, type y) \ #define SIZE 256 { \ int BUFFER_SIZE; return x > y ? x : y; \ } if (BUFFER_SIZE > SIZE) puts("Error: SIZE exceeded"); • An invocation of this macro: GENERIC_MAX(float) Appearance after preprocessing: int BUFFER_SIZE; • The resulting function definition: float float_max(float x, float y) { return x > y ? x : y; } if (BUFFER_SIZE > 256) puts("Error: SIZE exceeded");

42 Copyright © 2008 W. W. Norton & Company. 44 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor General Properties of Macros Parentheses in Macro Definitions • A macro definition normally remains in effect until • The replacement lists in macro definitions often require the end of the file in which it appears. parentheses in order to avoid unexpected results. Macros don’t obey normal scope rules. • If the macro’s replacement list contains an operator, A macro defined inside the body of a function isn’t always enclose the replacement list in parentheses: local to that function; it remains defined until the end #define TWO_PI (2*3.14159) of the file. • Also, put parentheses around each parameter every time it appears in the replacement list: • A macro may not be defined twice unless the new #define SCALE(x) ((x)*10) definition is identical to the old one. • Without the parentheses, we can’t guarantee that the Differences in spacing are allowed, but the tokens in compiler will treat replacement lists and arguments as the macro’s replacement list (and the parameters, if whole expressions. any) must be the same.

45 Copyright © 2008 W. W. Norton & Company. 47 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor General Properties of Macros Parentheses in Macro Definitions • Macros may be “undefined” by the #undef • An example that illustrates the need to put parentheses directive. around a macro’s replacement list: #define TWO_PI 2*3.14159 The #undef directive has the form /* needs parentheses around replacement list */ #undef identifier • During preprocessing, the statement where identifier is a macro name. conversion_factor = 360/TWO_PI; One use of #undef is to remove the existing becomes definition of a macro so that it can be given a new conversion_factor = 360/2*3.14159; definition. The division will be performed before the multiplication.

46 Copyright © 2008 W. W. Norton & Company. 48 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Parentheses in Macro Definitions Creating Longer Macros • Each occurrence of a parameter in a macro’s • An alternative definition of that uses braces: replacement list needs parentheses as well: #define ECHO(s) { gets(s); puts(s); } #define SCALE(x) (x*10) • Suppose that we use ECHO in an if statement: /* needs parentheses around x */ if (echo_flag) • During preprocessing, the statement ECHO(str); j = SCALE(i+1); else becomes gets(str); j = (i+1*10); • Replacing ECHO gives the following result: This statement is equivalent to if (echo_flag) j = i+10; { gets(str); puts(str); }; else gets(str);

49 Copyright © 2008 W. W. Norton & Company. 51 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Creating Longer Macros Creating Longer Macros • The comma operator can be useful for creating • The compiler treats the first two lines as a more sophisticated macros by allowing us to make complete if statement: the replacement list a series of expressions. if (echo_flag) • A macro that reads a string and then prints it: { gets(str); puts(str); } #define ECHO(s) (gets(s), puts(s)) • It treats the semicolon that follows as a null • Calls of gets and puts are expressions, so it’s statement and produces an error message for the perfectly legal to combine them using the comma else clause, since it doesn’t belong to any if. operator. • We could solve the problem by remembering not • We can invoke ECHO as though it were a function: to put a semicolon after each invocation of ECHO, ECHO(str); /* becomes (gets(str), puts(str)); */ but then the program would look odd.

50 Copyright © 2008 W. W. Norton & Company. 52 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Creating Longer Macros Predefined Macros • The comma operator solves this problem for • C has several predefined macros, each of which represents ECHO, but not for all macros. an integer constant or string literal. • The __DATE__ and __TIME__ macros identify when a • If a macro needs to contain a series of statements, program was compiled. not just a series of expressions, the comma • Example of using __DATE__ and __TIME__: operator is of no help. printf("Wacky Windows (c) 2010 Wacky Software, Inc.\n"); • The solution is to wrap the statements in a do loop printf("Compiled on %s at %s\n", __DATE__, __TIME__); whose condition is false: • Output produced by these statements: Wacky Windows (c) 2010 Wacky Software, Inc. do { … } while (0) Compiled on Dec 23 2010 at 22:18:48 • Notice that the do statement needs a semicolon at • This information can be helpful for distinguishing among the end. different versions of the same program.

53 Copyright © 2008 W. W. Norton & Company. 55 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Creating Longer Macros Predefined Macros • A modified version of the ECHO macro: • We can use the __LINE__ and __FILE__ macros to #define ECHO(s) \ help locate errors. do { \ • A macro that can help pinpoint the location of a gets(s); \ division by zero: puts(s); \ #define CHECK_ZERO(divisor) \ } while (0) if (divisor == 0) \ • When ECHO is used, it must be followed by a printf("*** Attempt to divide by zero on line %d " \ "of file %s ***\n", __LINE__, __FILE__) do semicolon, which completes the statement: • The CHECK_ZERO macro would be invoked prior to a ECHO(str); division: /* becomes CHECK_ZERO(j); do { gets(str); puts(str); } while (0); */ k=i/j;

54 Copyright © 2008 W. W. Norton & Company. 56 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Predefined Macros Additional Predefined Macros in C99 • If j happens to be zero, a message of the following • The __STDC__VERSION__ macro provides a form will be printed: way to check which version of the C standard is *** Attempt to divide by zero on line 9 of file foo.c *** recognized by the compiler. • Error-detecting macros like this one are quite useful. – If a compiler conforms to the C89 standard, including • In fact, the C library has a general-purpose error- Amendment 1, the value is 199409L. detecting macro named assert. – If a compiler conforms to the C99 standard, the value is • The remaining predefined macro is named __STDC__. 199901L. • This macro exists and has the value 1 if the compiler conforms to the C standard (either C89 or C99).

57 Copyright © 2008 W. W. Norton & Company. 59 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Additional Predefined Macros in C99 Additional Predefined Macros in C99 • C99 provides a few additional predefined macros. • A C99 compiler will define up to three additional • The __STDC__HOSTED__ macro represents the constant macros, but only if the compiler meets certain 1 if the compiler is a hosted implementation. Otherwise, requirements: the macro has the value 0. __STDC_IEC_559__ is defined (and has the value 1) if the • An implementation of C consists of the compiler plus compiler performs floating-point arithmetic according to IEC other software necessary to execute C programs. 60559. • A hosted implementation must accept any program that __STDC_IEC_559_COMPLEX__ is defined (and has the conforms to the C99 standard. value 1) if the compiler performs complex arithmetic • A freestanding implementation doesn’t have to compile according to IEC 60559. programs that use complex types or standard headers __STDC_ISO_10646__ is defined as yyyymmL if wide beyond a few of the most basic. characters are represented by the codes in ISO/IEC 10646 (with revisions as of the specified year and month).

58 Copyright © 2008 W. W. Norton & Company. 60 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Empty Macro Arguments (C99) Empty Macro Arguments (C99) • C99 allows any or all of the arguments in a macro • When an empty argument is an operand of the # call to be empty. or ## operators, special rules apply. • Such a call will contain the same number of • If an empty argument is “stringized” by the # commas as a normal call. operator, the result is "" (the empty string): • Wherever the corresponding parameter name #define MK_STR(x) #x appears in the replacement list, it’s replaced by … nothing. char empty_string[] = MK_STR(); • The declaration after preprocessing: char empty_string[] = "";

61 Copyright © 2008 W. W. Norton & Company. 63 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Empty Macro Arguments (C99) Empty Macro Arguments (C99) • Example: • If one of the arguments of the ## operator is #define ADD(x,y) (x+y) empty, it’s replaced by an invisible “placemarker” • After preprocessing, the statement token. i = ADD(j,k); • Concatenating an ordinary token with a becomes placemarker token yields the original token (the i = (j+k); placemarker disappears). whereas the statement • If two placemarker tokens are concatenated, the i = ADD(,k); result is a single placemarker. becomes • Once macro expansion has been completed, placemarker tokens disappear from the program. i = (+k);

62 Copyright © 2008 W. W. Norton & Company. 64 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Macros with a Variable Number Empty Macro Arguments (C99) of Arguments (C99) • Example: • An example that uses the TEST macro: #define JOIN(x,y,z) x##y##z TEST(voltage <= max_voltage, … "Voltage %d exceeds %d\n", voltage, max_voltage); int JOIN(a,b,c), JOIN(a,b,), JOIN(a,,c), JOIN(,,c); • Preprocessor output (reformatted for readability): • The declaration after preprocessing: ((voltage <= max_voltage)? printf("Passed test: %s\n", "voltage <= max_voltage"): int abc, ab, ac, c; printf("Voltage %d exceeds %d\n", voltage, max_voltage)); • The missing arguments were replaced by placemarker • The program will display the message tokens, which then disappeared when concatenated with Passed test: voltage <= max_voltage any nonempty arguments. if voltage is no more than max_voltage. • All three arguments to the JOIN macro could even be • Otherwise, it will display the values of voltage and missing, which would yield an empty result. max_voltage: Voltage 125 exceeds 120

65 Copyright © 2008 W. W. Norton & Company. 67 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Macros with a Variable Number The __func__ Identifier (C99) of Arguments (C99) • C99 allows macros that take an unlimited number of • The __func__ identifier behaves like a string arguments. variable that stores the name of the currently • A macro of this kind can pass its arguments to a function executing function. that accepts a variable number of arguments. • The effect is the same as if each function contains the • Example: following declaration at the beginning of its body: #define TEST(condition, ...) ((condition)? \ static const char __func__[] = "function-name"; printf("Passed test: %s\n", #condition): \ printf(__VA_ARGS__)) where function-name is the name of the function. • The ... token (ellipsis) goes at the end of the parameter list, preceded by ordinary parameters, if any. • __VA_ARGS__ is a special identifier that represents all the arguments that correspond to the ellipsis.

66 Copyright © 2008 W. W. Norton & Company. 68 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor The __func__ Identifier (C99) The #if and #endif Directives • Debugging macros that rely on the __func__ identifier: • Suppose we’re in the process of debugging a #define FUNCTION_CALLED() printf("%s called\n", __func__); program. #define FUNCTION_RETURNS() printf("%s returns\n", __func__); • These macros can used to trace function calls: • We’d like the program to print the values of void f(void) certain variables, so we put calls of printf in { FUNCTION_CALLED(); /* displays "f called" */ critical parts of the program. … • Once we’ve located the bugs, it’s often a good FUNCTION_RETURNS(); /* displays "f returns" */ } idea to let the printf calls remain, just in case • Another use of __func__: it can be passed to a function to we need them later. let it know the name of the function that called it. • Conditional compilation allows us to leave the calls in place, but have the compiler ignore them.

69 Copyright © 2008 W. W. Norton & Company. 71 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Conditional Compilation The #if and #endif Directives • The recognizes a number of • The first step is to define a macro and give it a directives that support conditional compilation. nonzero value: • This feature permits the inclusion or exclusion of a #define DEBUG 1 section of program text depending on the outcome • Next, we’ll surround each group of printf calls of a test performed by the preprocessor. by an #if-#endif pair: #if DEBUG printf("Value of i: %d\n", i); printf("Value of j: %d\n", j); #endif

70 Copyright © 2008 W. W. Norton & Company. 72 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor The #if and #endif Directives The #if and #endif Directives • During preprocessing, the #if directive will test • The #if directive treats undefined identifiers as the value of DEBUG. macros that have the value 0. • Since its value isn’t zero, the preprocessor will • If we neglect to define DEBUG, the test leave the two calls of printf in the program. #if DEBUG • If we change the value of DEBUG to zero and will fail (but not generate an error message). recompile the program, the preprocessor will • The test remove all four lines from the program. #if !DEBUG • The #if-#endif blocks can be left in the final will succeed. program, allowing diagnostic information to be produced later if any problems turn up.

73 Copyright © 2008 W. W. Norton & Company. 75 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor The #if and #endif Directives The defined Operator • General form of the #if and #endif directives: • The preprocessor supports three operators: #, ##, #if constant-expression and defined. #endif • When applied to an identifier, defined produces • When the preprocessor encounters the #if the value 1 if the identifier is a currently defined directive, it evaluates the constant expression. macro; it produces 0 otherwise. • If the value of the expression is zero, the lines • The defined operator is normally used in between #if and #endif will be removed from conjunction with the #if directive. the program during preprocessing. • Otherwise, the lines between #if and #endif will remain.

74 Copyright © 2008 W. W. Norton & Company. 76 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor The defined Operator The #elif and #else Directives • Example: • #if, #ifdef, and #ifndef blocks can be #if defined(DEBUG) nested just like ordinary if statements. … • When nesting occurs, it’s a good idea to use an #endif increasing amount of indentation as the level of • The lines between #if and #endif will be nesting grows. included only if DEBUG is defined as a macro. • Some programmers put a comment on each closing • The parentheses around DEBUG aren’t required: #endif to indicate what condition the matching #if defined DEBUG #if tests: • It’s not necessary to give DEBUG a value: #if DEBUG … #define DEBUG #endif /* DEBUG */

77 Copyright © 2008 W. W. Norton & Company. 79 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor The #ifdef and #ifndef Directives The #elif and #else Directives • The #ifdef directive tests whether an identifier • #elif and #else can be used in conjunction with is currently defined as a macro: #if, #ifdef, or #ifndef to test a series of #ifdef identifier conditions: • The effect is the same as #if expr1 Lines to be included if expr1 is nonzero #if defined(identifier) #elif expr2 • The #ifndef directive tests whether an identifier Lines to be included if expr1 is zero but expr2 is nonzero is not currently defined as a macro: #else Lines to be included otherwise #ifndef identifier #endif • The effect is the same as • Any number of #elif directives—but at most one #if !defined(identifier) #else—may appear between #if and #endif.

78 Copyright © 2008 W. W. Norton & Company. 80 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Uses of Conditional Compilation Uses of Conditional Compilation • Conditional compilation has other uses besides • Providing a default definition for a macro. debugging. Conditional compilation makes it possible to • Writing programs that are portable to several check whether a macro is currently defined and, if machines or operating systems. not, give it a default definition: Example: #ifndef BUFFER_SIZE #if defined(WIN32) #define BUFFER_SIZE 256 … #endif #elif defined(MAC_OS) … #elif defined(LINUX) … #endif

81 Copyright © 2008 W. W. Norton & Company. 83 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Uses of Conditional Compilation Uses of Conditional Compilation • Writing programs that can be compiled with • Temporarily disabling code that contains different compilers. comments. An example that uses the __STDC__ macro: A /*…*/ comment can’t be used to “comment #if __STDC__ out” code that already contains /*…*/ Function prototypes comments. #else An #if directive can be used instead: Old-style function declarations #endif #if 0 Lines containing comments If the compiler does not conform to the C #endif standard, old-style function declarations are used instead of function prototypes.

82 Copyright © 2008 W. W. Norton & Company. 84 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor Uses of Conditional Compilation The #error Directive • Chapter 15 discusses another common use of • Form of the #error directive: conditional compilation: protecting header files #error message against multiple inclusion. message is any sequence of tokens. • If the preprocessor encounters an #error directive, it prints an error message which must include message. • If an #error directive is processed, some compilers immediately terminate compilation without attempting to find other errors.

85 Copyright © 2008 W. W. Norton & Company. 87 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor Miscellaneous Directives The #error Directive • The #error, #line, and #pragma directives • #error directives are frequently used in are more specialized than the ones we’ve already conjunction with conditional compilation. examined. • Example that uses an #error directive to test the • These directives are used much less frequently. maximum value of the int type: #if INT_MAX < 100000 #error int type is too small #endif

86 Copyright © 2008 W. W. Norton & Company. 88 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor The #error Directive The #line Directive • The #error directive is often found in the • The #line directive changes the value of the #else part of an #if-#elif-#else series: __LINE__ macro (and possibly __FILE__). #if defined(WIN32) • Most compilers will use the information from the … #line directive when generating error messages. #elif defined(MAC_OS) • Suppose that the following directive appears at the … beginning of foo.c: #elif defined(LINUX) #line 10 "bar.c" … #else If the compiler detects an error on line 5 of foo.c, #error No operating system specified the message will refer to line 13 of file bar.c. #endif • The #line directive is used primarily by programs that generate C code as output.

89 Copyright © 2008 W. W. Norton & Company. 91 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor The #line Directive The #line Directive • The #line directive is used to alter the way • The most famous example is (Yet Another program lines are numbered. Compiler-Compiler), a UNIX utility that automatically generates part of a compiler. • First form of the #line directive: • The programmer prepares a file that contains information #line n for yacc as well as fragments of C code. Subsequent lines in the program will be numbered • From this file, yacc generates a C program, y.tab.c, n, n + 1, n + 2, and so forth. that incorporates the code supplied by the programmer. • Second form of the #line directive: • By inserting #line directives, yacc tricks the compiler into believing that the code comes from the original file. #line n "file" • Error messages produced during the compilation of Subsequent lines are assumed to come from file, y.tab.c will refer to lines in the original file. with line numbers starting at n.

90 Copyright © 2008 W. W. Norton & Company. 92 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 14: The Preprocessor The #pragma Directive The _Pragma Operator (C99) • The #pragma directive provides a way to request • C99 introduces the _Pragma operator, which is special behavior from the compiler. used in conjunction with the #pragma directive. • Form of a #pragma directive: • A _Pragma expression has the form #pragma tokens _Pragma ( string-literal ) • #pragma directives can be very simple (a single • When it encounters such an expression, the token) or they can be much more elaborate: preprocessor “destringizes” the string literal: #pragma data(heap_size => 1000, stack_size => 2000) – Double quotes around the string are removed. –\"is replaced by ". –\\is replaced by \.

93 Copyright © 2008 W. W. Norton & Company. 95 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 14: The Preprocessor The #pragma Directive The _Pragma Operator (C99) • The set of commands that can appear in #pragma • The resulting tokens are then treated as though directives is different for each compiler. they appear in a #pragma directive. • The preprocessor must ignore any #pragma • For example, writing directive that contains an unrecognized command; _Pragma("data(heap_size => 1000, stack_size => 2000)") it’s not permitted to give an error message. is the same as writing • In C89, there are no standard pragmas—they’re all #pragma data(heap_size => 1000, stack_size => 2000) implementation-defined. • C99 has three standard pragmas, all of which use STDC as the first token following #pragma.

94 Copyright © 2008 W. W. Norton & Company. 96 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 14: The Preprocessor Chapter 15: Writing Large Programs The _Pragma Operator (C99) • The _Pragma operator lets us work around the fact that a preprocessing directive can’t generate another directive. Chapter 15 • _Pragma, however, is an operator, not a directive, and can therefore appear in a macro definition. Writing Large Programs • This makes it possible for a macro expansion to leave behind a #pragma directive.

97 Copyright © 2008 W. W. Norton & Company. 1 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 14: The Preprocessor Chapter 15: Writing Large Programs The _Pragma Operator (C99) Source Files • A macro that uses the _Pragma operator: • A C program may be divided among any number #define DO_PRAGMA(x) _Pragma(#x) of source files. • An invocation of the macro: • By convention, source files have the extension .c. DO_PRAGMA(GCC dependency "parse.y") • Each source file contains part of the program, • The result after expansion: primarily definitions of functions and variables. #pragma GCC dependency "parse.y" • One source file must contain a function named • The tokens passed to DO_PRAGMA are stringized main, which serves as the starting point for the into "GCC dependency \"parse.y\"". program. • The _Pragma operator destringizes this string, producing a #pragma directive.

98 Copyright © 2008 W. W. Norton & Company. 2 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Source Files Source Files • Consider the problem of writing a simple • How the expression 30 5 - 7 *: will be evaluated: calculator program. 1. Push 30 onto the stack. • The program will evaluate integer expressions 2. Push 5 onto the stack. entered in Reverse Polish notation (RPN), in 3. Pop the top two numbers from the stack, subtract 5 which operators follow operands. from 30, giving 25, and then push the result back onto the stack. • If the user enters an expression such as 4. Push 7 onto the stack. 30 5 - 7 * 5. Pop the top two numbers from the stack, multiply the program should print its value (175, in this them, and then push the result back onto the stack. case). • The stack will now contain 175, the value of the expression.

3 Copyright © 2008 W. W. Norton & Company. 5 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Source Files Source Files • The program will read operands and operators, • The program’s main function will contain a loop one by one, using a stack to keep track of that performs the following actions: intermediate results. – Read a “token” (a number or an operator). – If the program reads a number, it will push the number – If the token is a number, push it onto the stack. onto the stack. – If the token is an operator, pop its operands from the – If the program reads an operator, it will pop two stack, perform the operation, and then push the result numbers from the stack, perform the operation, and back onto the stack. then push the result back onto the stack. • When dividing a program like this one into files, it • When the program reaches the end of the user’s makes sense to put related functions and variables input, the value of the expression will be on the into the same file. stack.

4 Copyright © 2008 W. W. Norton & Company. 6 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Source Files Header Files • The function that reads tokens could go into one • Problems that arise when a program is divided into source file (token.c, say), together with any several source files: functions that have to do with tokens. – How can a function in one file call a function that’s • Stack-related functions such as push, pop, defined in another file? make_empty, is_empty, and is_full could – How can a function access an external variable in go into a different file, stack.c. another file? – How can two files share the same macro definition or • The variables that represent the stack would also type definition? go into stack.c. • The answer lies with the #include directive, • The main function would go into yet another file, which makes it possible to share information calc.c. among any number of source files.

7 Copyright © 2008 W. W. Norton & Company. 9 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Source Files Header Files • Splitting a program into multiple source files has • The #include directive tells the preprocessor to significant advantages: insert the contents of a specified file. – Grouping related functions and variables into a single • Information to be shared among several source file helps clarify the structure of the program. files can be put into such a file. – Each source file can be compiled separately, which • #include can then be used to bring the file’s saves time. contents into each of the source files. – Functions are more easily reused in other programs when grouped in separate source files. • Files that are included in this fashion are called header files (or sometimes include files). • By convention, header files have the extension .h.

8 Copyright © 2008 W. W. Norton & Company. 10 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs The #include Directive The #include Directive • The #include directive has two primary forms. • Don’t use brackets when including header files • The first is used for header files that belong to C’s that you have written: own library: #include /*** WRONG ***/ #include • The preprocessor will probably look for • The second is used for all other header files: myheader.h where the system header files are #include "filename" kept. • The difference between the two has to do with how the compiler locates the header file.

11 Copyright © 2008 W. W. Norton & Company. 13 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs The #include Directive The #include Directive • Typical rules for locating header files: • The file name in an #include directive may – #include : Search the directory (or include information that helps locate the file, such directories) in which system header files reside. as a directory path or drive specifier: – #include "filename": Search the current directory, #include "c:\cprogs\utils.h" then search the directory (or directories) in which /* Windows path */ system header files reside. • The places to be searched for header files can #include "/cprogs/utils.h" /* UNIX path */ usually be altered, often by a command-line option such as -Ipath. • Although the quotation marks in the #include directive make file names look like string literals, the preprocessor doesn’t treat them that way.

12 Copyright © 2008 W. W. Norton & Company. 14 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs The #include Directive The #include Directive • It’s usually best not to include path or drive • Example: information in #include directives. #if defined(IA32) • Bad examples of Windows #include directives: #define CPU_FILE "ia32.h" #elif defined(IA64) #include "d:utils.h" #define CPU_FILE "ia64.h" #include "\cprogs\include\utils.h" #elif defined(AMD64) #include "d:\cprogs\include\utils.h" #define CPU_FILE "amd64.h" • Better versions: #endif #include "utils.h" #include "..\include\utils.h" #include CPU_FILE

15 Copyright © 2008 W. W. Norton & Company. 17 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs

The #include Directive Sharing Macro Definitions and Type Definitions • The #include directive has a third form: • Most large programs contain macro definitions #include tokens and type definitions that need to be shared by tokens is any sequence of preprocessing tokens. several source files. • The preprocessor will scan the tokens and replace • These definitions should go into header files. any macros that it finds. • After macro replacement, the resulting directive must match one of the other forms of #include. • The advantage of the third kind of #include is that the file name can be defined by a macro rather than being “hard-coded” into the directive itself.

16 Copyright © 2008 W. W. Norton & Company. 18 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs

Sharing Macro Definitions and Type Definitions Sharing Macro Definitions and Type Definitions • Suppose that a program uses macros named BOOL, • Type definitions are also common in header files. TRUE, and FALSE. • For example, instead of defining a BOOL macro, • Their definitions can be put in a header file with a we might use typedef to create a Bool type. name like boolean.h: • If we do, the boolean.h file will have the #define BOOL int following appearance: #define TRUE 1 #define TRUE 1 #define FALSE 0 #define FALSE 0 • Any source file that requires these macros will typedef int Bool; simply contain the line #include "boolean.h"

19 Copyright © 2008 W. W. Norton & Company. 21 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs

Sharing Macro Definitions and Type Definitions Sharing Macro Definitions and Type Definitions • A program in which two files include boolean.h: • Advantages of putting definitions of macros and types in header files: – Saves time. We don’t have to copy the definitions into the source files where they’re needed. – Makes the program easier to modify. Changing the definition of a macro or type requires editing a single header file. – Avoids inconsistencies caused by source files containing different definitions of the same macro or type.

20 Copyright © 2008 W. W. Norton & Company. 22 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Sharing Function Prototypes Sharing Function Prototypes • Suppose that a source file contains a call of a • If foo.c contains other functions, most of them function f that’s defined in another file, foo.c. should be declared in foo.h. • Calling f without declaring it first is risky. • Functions that are intended for use only within – The compiler assumes that f’s return type is int. foo.c shouldn’t be declared in a header file, – It also assumes that the number of parameters matches however; to do so would be misleading. the number of arguments in the call of f. – The arguments themselves are converted automatically by the default argument promotions.

23 Copyright © 2008 W. W. Norton & Company. 25 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Sharing Function Prototypes Sharing Function Prototypes • Declaring f in the file where it’s called solves the • The RPN calculator example can be used to illustrate problem but can create a maintenance nightmare. the use of function prototypes in header files. • A better solution is to put f’s prototype in a • The stack.c file will contain definitions of the header file (foo.h), then include the header file make_empty, is_empty, is_full, push, and in all the places where f is called. pop functions. • We’ll also need to include foo.h in foo.c, • Prototypes for these functions should go in the stack.h header file: enabling the compiler to check that f’s prototype void make_empty(void); in foo.h matches its definition in foo.c. int is_empty(void); int is_full(void); void push(int i); int pop(void);

24 Copyright © 2008 W. W. Norton & Company. 26 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Sharing Function Prototypes Sharing Variable Declarations • We’ll include stack.h in calc.c to allow the • To share a function among files, we put its compiler to check any calls of stack functions that definition in one source file, then put declarations appear in the latter file. in other files that need to call the function. • We’ll also include stack.h in stack.c so the • Sharing an external variable is done in much the compiler can verify that the prototypes in same way. stack.h match the definitions in stack.c.

27 Copyright © 2008 W. W. Norton & Company. 29 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Sharing Function Prototypes Sharing Variable Declarations • An example that both declares and defines i (causing the compiler to set aside space): int i; • The keyword extern is used to declare a variable without defining it: extern int i; • extern informs the compiler that i is defined elsewhere in the program, so there’s no need to allocate space for it.

28 Copyright © 2008 W. W. Norton & Company. 30 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Sharing Variable Declarations Sharing Variable Declarations • When we use extern in the declaration of an • When declarations of the same variable appear in array, we can omit the length of the array: different files, the compiler can’t check that the extern int a[]; declarations match the variable’s definition. • Since the compiler doesn’t allocate space for a at • For example, one file may contain the definition this time, there’s no need for it to know a’s length. int i; while another file contains the declaration extern long i; • An error of this kind can cause the program to behave unpredictably.

31 Copyright © 2008 W. W. Norton & Company. 33 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Sharing Variable Declarations Sharing Variable Declarations • To share a variable i among several source files, • To avoid inconsistency, declarations of shared we first put a definition of i in one file: variables are usually put in header files. int i; • A source file that needs access to a particular • If i needs to be initialized, the initializer would go variable can then include the appropriate header here. file. • The other files will contain declarations of i: • In addition, each header file that contains a extern int i; variable declaration is included in the source file • By declaring i in each file, it becomes possible to that contains the variable’s definition, enabling the access and/or modify i within those files. compiler to check that the two match.

32 Copyright © 2008 W. W. Norton & Company. 34 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Nested Includes Protecting Header Files • A header file may contain #include directives. • If a source file includes the same header file twice, • stack.h contains the following prototypes: compilation errors may result. int is_empty(void); • This problem is common when header files int is_full(void); include other header files. • Since these functions return only 0 or 1, it’s a good • Suppose that file1.h includes file3.h, idea to declare their return type to be Bool: file2.h includes file3.h, and prog.c Bool is_empty(void); includes both file1.h and file2.h. Bool is_full(void); • We’ll need to include the boolean.h file in stack.h so that the definition of Bool is available when stack.h is compiled.

35 Copyright © 2008 W. W. Norton & Company. 37 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Nested Includes Protecting Header Files • Traditionally, C programmers shun nested includes. • However, the bias against nested includes has largely faded away, in part because nested includes are common practice in C++.

• When prog.c is compiled, file3.h will be compiled twice.

36 Copyright © 2008 W. W. Norton & Company. 38 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Protecting Header Files Protecting Header Files • Including the same header file twice doesn’t • To protect a header file, we’ll enclose the contents always cause a compilation error. of the file in an #ifndef-#endif pair. • If the file contains only macro definitions, • How to protect the boolean.h file: function prototypes, and/or variable declarations, #ifndef BOOLEAN_H there won’t be any difficulty. #define BOOLEAN_H • If the file contains a type definition, however, #define TRUE 1 we’ll get a compilation error. #define FALSE 0 typedef int Bool;

#endif

39 Copyright © 2008 W. W. Norton & Company. 41 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Protecting Header Files Protecting Header Files • Just to be safe, it’s probably a good idea to protect • Making name of the macro resemble the name of all header files against multiple inclusion. the header file is a good way to avoid conflicts • That way, we can add type definitions to a file with other macros. later without the risk that we might forget to • Since we can’t name the macro BOOLEAN.H, a protect the file. name such as BOOLEAN_H is a good alternative. • In addition, we might save some time during program development by avoiding unnecessary recompilation of the same header file.

40 Copyright © 2008 W. W. Norton & Company. 42 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs #error Directives in Header Files Dividing a Program into Files • #error directives are often put in header files to • Each set of functions will go into a separate source file check for conditions under which the header file (foo.c). shouldn’t be included. • Each source file will have a matching header file (foo.h). – foo.h • Suppose that a header file uses a feature that didn’t will contain prototypes for the functions defined in foo.c. exist prior to the original C89 standard. – Functions to be used only within foo.c should not be • An #ifndef directive that tests for the existence declared in foo.h. of the __STDC__ macro: • foo.h will be included in each source file that needs to #ifndef __STDC__ call a function defined in foo.c. #error This header requires a Standard C compiler • foo.h foo.c #endif will also be included in so the compiler can check that the prototypes in foo.h match the definitions in foo.c.

43 Copyright © 2008 W. W. Norton & Company. 45 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Dividing a Program into Files Dividing a Program into Files • Designing a program involves determining what • The main function will go in a file whose name functions it will need and arranging the functions matches the name of the program. into logically related groups. • It’s possible that there are other functions in the • Once a program has been designed, there is a same file as main, so long as they’re not called simple technique for dividing it into files. from other files in the program.

44 Copyright © 2008 W. W. Norton & Company. 46 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Program: Text Formatting Program: Text Formatting • Let’s apply this technique to a small text- • Output of justify: formatting program named justify. C is quirky, flawed, and an enormous success. Although accidents of history surely helped, it evidently satisfied a • Assume that a file named quote contains the need for a system implementation language efficient enough to displace assembly language, yet sufficiently abstract and following sample input: fluent to describe algorithms and interactions in a wide C is quirky, flawed, and an variety of environments. -- Dennis M. Ritchie enormous success. Although accidents of history • The output of justify will normally appear on the surely helped, it evidently satisfied a need screen, but we can save it in a file by using output for a system implementation language efficient redirection: enough to displace assembly language, yet sufficiently abstract and fluent to describe justify newquote algorithms and interactions in a wide variety of environments. -- Dennis M. Ritchie

47 Copyright © 2008 W. W. Norton & Company. 49 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Program: Text Formatting Program: Text Formatting • To run the program from a UNIX or Windows • justify will delete extra spaces and blank lines prompt, we’d enter the command as well as filling and justifying lines. justify

48 Copyright © 2008 W. W. Norton & Company. 50 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Program: Text Formatting Program: Text Formatting • We assume that no word is longer than 20 • The heart of the program will be a loop: characters, including any adjacent punctuation. for (;;) { • If the program encounters a longer word, it must read word; ignore all characters after the first 20, replacing if (can’t read word) { write contents of line buffer without justification; them with a single asterisk. terminate program; • For example, the word } if (word doesn’t fit in line buffer) { antidisestablishmentarianism write contents of line buffer with justification; would be printed as clear line buffer; antidisestablishment* } add word to line buffer; }

51 Copyright © 2008 W. W. Norton & Company. 53 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Program: Text Formatting Program: Text Formatting • The program can’t write words one by one as • The program will be split into three source files: they’re read. – word.c: functions related to words • Instead, it will have to store them in a “line – line.c: functions related to the line buffer buffer” until there are enough to fill a line. – justify.c: contains the main function • We’ll also need two header files: – word.h: prototypes for the functions in word.c – line.h: prototypes for the functions in line.c • word.h will contain the prototype for a function that reads a word.

52 Copyright © 2008 W. W. Norton & Company. 54 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs word.h line.h #ifndef WORD_H #ifndef LINE_H #define WORD_H #define LINE_H

/********************************************************** /********************************************************** * read_word: Reads the next word from the input and * * clear_line: Clears the current line. * * stores it in word. Makes word empty if no * **********************************************************/ * word could be read because of end-of-file. * void clear_line(void); * Truncates the word if its length exceeds * * len. * /********************************************************** **********************************************************/ * add_word: Adds word to the end of the current line. * void read_word(char *word, int len); * If this is not the first word on the line, * * puts one space before word. * #endif **********************************************************/ void add_word(const char *word);

55 Copyright © 2008 W. W. Norton & Company. 57 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs

/********************************************************** Program: Text Formatting * space_remaining: Returns the number of characters left * * in the current line. * **********************************************************/ • The outline of the main loop reveals the need for int space_remaining(void); functions that perform the following operations: /********************************************************** – Write contents of line buffer without justification * write_line: Writes the current line with * – Determine how many characters are left in line buffer * justification. * **********************************************************/ – Write contents of line buffer with justification void write_line(void);

– Clear line buffer /********************************************************** – Add word to line buffer * flush_line: Writes the current line without * * justification. If the line is empty, does * • We’ll call these functions flush_line, * nothing. * **********************************************************/ space_remaining, write_line, void flush_line(void); clear_line, and add_word. #endif

56 Copyright © 2008 W. W. Norton & Company. 58 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs

clear_line(); Program: Text Formatting for (;;) { read_word(word, MAX_WORD_LEN+1); • Before we write the word.c and line.c files, word_len = strlen(word); if (word_len == 0) { we can use the functions declared in word.h and flush_line(); return 0; line.h to write justify.c, the main } program. if (word_len > MAX_WORD_LEN) word[MAX_WORD_LEN] = '*'; • Writing this file is mostly a matter of translating if (word_len + 1 > space_remaining()) { write_line(); the original loop design into C. clear_line(); } add_word(word); } }

59 Copyright © 2008 W. W. Norton & Company. 61 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs justify.c Program: Text Formatting /* Formats a file of text */ • main uses a trick to handle words that exceed 20 #include #include "line.h" characters. #include "word.h" • When it calls read_word, main tells it to #define MAX_WORD_LEN 20 truncate any word that exceeds 21 characters. int main(void) • After read_word returns, main checks whether { char word[MAX_WORD_LEN+2]; word contains a string that’s longer than 20 int word_len; characters. • If so, the word must have been at least 21 characters long (before truncation), so main replaces its 21st character by an asterisk.

60 Copyright © 2008 W. W. Norton & Company. 62 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs

void read_word(char *word, int len) Program: Text Formatting { int ch, pos = 0; • The word.h header file has a prototype for only while ((ch = read_char()) == ' ') one function, read_word. ; while (ch != ' ' && ch != EOF) { • read_word is easier to write if we add a small if (pos < len) read_char word[pos++] = ch; “helper” function, . ch = read_char(); • read_char’s job is to read a single character } word[pos] = '\0'; and, if it’s a new-line character or tab, convert it to } a space. • Having read_word call read_char instead of getchar solves the problem of treating new-line characters and tabs as spaces.

63 Copyright © 2008 W. W. Norton & Company. 65 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs word.c Program: Text Formatting #include #include "word.h" • line.c supplies definitions of the functions int read_char(void) declared in line.h. { int ch = getchar(); • line.c will also need variables to keep track of the state of the line buffer: if (ch == '\n' || ch == '\t') return ' '; – line: characters in the current line return ch; – line_len: number of characters in the current line } – num_words: number of words in the current line

64 Copyright © 2008 W. W. Norton & Company. 66 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs

void write_line(void) line.c { int extra_spaces, spaces_to_insert, i, j; #include #include extra_spaces = MAX_LINE_LEN - line_len; #include "line.h" for (i = 0; i < line_len; i++) { #define MAX_LINE_LEN 60 if (line[i] != ' ') putchar(line[i]); else { char line[MAX_LINE_LEN+1]; spaces_to_insert = extra_spaces / (num_words - 1); int line_len = 0; for (j = 1; j <= spaces_to_insert + 1; j++) int num_words = 0; putchar(' '); extra_spaces -= spaces_to_insert; void clear_line(void) num_words--; { } line[0] = '\0'; } putchar('\n'); line_len = 0; } num_words = 0; } void flush_line(void) { if (line_len > 0) puts(line); }

67 Copyright © 2008 W. W. Norton & Company. 69 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs void add_word(const char *word) { Building a Multiple-File Program if (num_words > 0) { line[line_len] = ' '; line[line_len+1] = '\0'; • Building a large program requires the same basic line_len++; steps as building a small one: } strcat(line, word); – Compiling line_len += strlen(word); – Linking num_words++; } int space_remaining(void) { return MAX_LINE_LEN - line_len; }

68 Copyright © 2008 W. W. Norton & Company. 70 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Building a Multiple-File Program Building a Multiple-File Program • Each source file in the program must be compiled • Most compilers allow us to build a program in a separately. single step. • Header files don’t need to be compiled. • A GCC command that builds justify: • The contents of a header file are automatically gcc -o justify justify.c line.c word.c compiled whenever a source file that includes it is • The three source files are first compiled into compiled. object code. • For each source file, the compiler generates a file • The object files are then automatically passed to containing object code. the linker, which combines them into a single file. • These files—known as object files—have the • The -o option specifies that we want the extension .o in UNIX and .obj in Windows. executable file to be named justify.

71 Copyright © 2008 W. W. Norton & Company. 73 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Building a Multiple-File Program Makefiles • The linker combines the object files created in the • To make it easier to build large programs, UNIX previous step—along with code for library originated the concept of the makefile. functions—to produce an executable file. • A makefile not only lists the files that are part of • Among other duties, the linker is responsible for the program, but also describes dependencies resolving external references left behind by the among the files. compiler. • Suppose that the file foo.c includes the file • An external reference occurs when a function in bar.h. one file calls a function defined in another file or • We say that foo.c “depends” on bar.h, accesses a variable defined in another file. because a change to bar.h will require us to recompile foo.c.

72 Copyright © 2008 W. W. Norton & Company. 74 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Makefiles Makefiles • A UNIX makefile for the justify program: • In the first rule, justify (the executable file) is the justify: justify.o word.o line.o target: gcc -o justify justify.o word.o line.o justify: justify.o word.o line.o gcc -o justify justify.o word.o line.o justify.o: justify.c word.h line.h • The first line states that justify depends on the gcc -c justify.c files justify.o, word.o, and line.o. word.o: word.c word.h • If any of these files have changed since the program gcc -c word.c was last built, justify needs to be rebuilt. line.o: line.c line.h • The command on the following line shows how the gcc -c line.c rebuilding is to be done.

75 Copyright © 2008 W. W. Norton & Company. 77 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Makefiles Makefiles • There are four groups of lines; each group is • In the second rule, justify.o is the target: known as a rule. justify.o: justify.c word.h line.h • The first line in each rule gives a target file, gcc -c justify.c followed by the files on which it depends. • The first line indicates that justify.o needs to • The second line is a command to be executed if be rebuilt if there’s been a change to the target should need to be rebuilt because of a justify.c, word.h, or line.h. change to one of its dependent files. • The next line shows how to update justify.o (by recompiling justify.c). • The -c option tells the compiler to compile justify.c but not attempt to link it.

76 Copyright © 2008 W. W. Norton & Company. 78 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Makefiles Makefiles • Once we’ve created a makefile for a program, we • To invoke make, use the command can use the make utility to build (or rebuild) the make target program. where target is one of the targets listed in the • By checking the time and date associated with makefile. each file in the program, make can determine • If no target is specified when make is invoked, it which files are out of date. will build the target of the first rule. • It then invokes the commands necessary to rebuild • Except for this special property of the first rule, the program. the order of rules in a makefile is arbitrary.

79 Copyright © 2008 W. W. Norton & Company. 81 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Makefiles Makefiles • Each command in a makefile must be preceded by • Real makefiles aren’t always easy to understand. a tab character, not a series of spaces. • There are numerous techniques that reduce the • A makefile is normally stored in a file named amount of redundancy in makefiles and make Makefile (or makefile). them easier to modify. • When the make utility is used, it automatically • These techniques greatly reduce the readability of checks the current directory for a file with one of makefiles. these names. • Alternatives to makefiles include the “project files” supported by some integrated development environments.

80 Copyright © 2008 W. W. Norton & Company. 82 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Errors During Linking Rebuilding a Program • Some errors that can’t be detected during • During the development of a program, it’s rare compilation will be found during linking. that we’ll need to compile all its files. • If the definition of a function or variable is • To save time, the rebuilding process should missing from a program, the linker will be unable recompile only those files that might be affected to resolve external references to it by the latest change. • The result is a message such as “undefined • Assume that a program has been designed with a symbol” or “undefined reference.” header file for each source file. • To see how many files will need to be recompiled after a change, we need to consider two possibilities.

83 Copyright © 2008 W. W. Norton & Company. 85 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Errors During Linking Rebuilding a Program • Common causes of errors during linking: • If the change affects a single source file, only that file – Misspellings. If the name of a variable or function is must be recompiled. misspelled, the linker will report it as missing. • Suppose that we decide to condense the read_char – Missing files. If the linker can’t find the functions that function in word.c: are in file foo.c, it may not know about the file. int read_char(void) – Missing libraries. The linker may not be able to find all { library functions used in the program. int ch = getchar(); • In UNIX, the -lm option may need to be specified return (ch == '\n' || ch == '\t') ? ' ' : ch; when a program that uses is linked. } • This modification doesn’t affect word.h, so we need only recompile word.c and relink the program.

84 Copyright © 2008 W. W. Norton & Company. 86 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Rebuilding a Program Rebuilding a Program • The second possibility is that the change affects a • Next, we change the definition of read_word: header file. int read_word(char *word, int len) { • In that case, we should recompile all files that int ch, pos = 0; include the header file, since they could while ((ch = read_char()) == ' ') potentially be affected by the change. ; while (ch != ' ' && ch != EOF) { if (pos < len) word[pos++] = ch; ch = read_char(); } word[pos] = '\0'; return pos; }

87 Copyright © 2008 W. W. Norton & Company. 89 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Rebuilding a Program Rebuilding a Program • Suppose that we modify read_word so that it returns • Finally, we modify justify.c by removing the the length of the word that it reads. include of and changing main: • First, we change the prototype of read_word in int main(void) { word.h: char word[MAX_WORD_LEN+2]; /********************************************************** int word_len; * read_word: Reads the next word from the input and * * stores it in word. Makes word empty if no * clear_line(); * word could be read because of end-of-file. * for (;;) { * Truncates the word if its length exceeds * word_len = read_word(word, MAX_WORD_LEN+1); * len. Returns the number of characters * … * stored. * **********************************************************/ } int read_word(char *word, int len); }

88 Copyright © 2008 W. W. Norton & Company. 90 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Rebuilding a Program Rebuilding a Program • Once we’ve made these changes, we’ll rebuild • Suppose that we make the indicated changes to justify by recompiling word.c and word.h, word.c, and justify.c. justify.c and then relinking. • When the justify program is rebuilt, make • A GCC command that rebuilds the program: will perform the following actions: gcc -o justify justify.c word.c line.o 1. Build justify.o by compiling justify.c (because justify.c and word.h were changed). 2. Build word.o by compiling word.c (because word.c and word.h were changed). 3. Build justify by linking justify.o, word.o, and line.o (because justify.o and word.o were changed).

91 Copyright © 2008 W. W. Norton & Company. 93 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 15: Writing Large Programs Chapter 15: Writing Large Programs Rebuilding a Program Defining Macros Outside a Program • One of the advantages of using makefiles is that • C compilers usually provide some method of rebuilding is handled automatically. specifying the value of a macro at the time a • By examining the date of each file, make can program is compiled. determine which files have changed since the • This ability makes it easy to change the value of a program was last built. macro without editing any of the program’s files. • It then recompiles these files, together with all • It’s especially valuable when programs are built files that depend on them, either directly or automatically using makefiles. indirectly.

92 Copyright © 2008 W. W. Norton & Company. 94 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 15: Writing Large Programs Chapter 16: Structures, Unions, and Enumerations Defining Macros Outside a Program • Most compilers (including GCC) support the -D option, which allows the value of a macro to be specified on the command line: gcc -DDEBUG=1 foo.c Chapter 16 • In this example, the DEBUG macro is defined to have the value 1 in the program foo.c. Structures, Unions, • If the -D option names a macro without specifying and Enumerations its value, the value is taken to be 1.

1 Copyright © 2008 W. W. Norton & Company. All rights reserved. 95 Copyright © 2008 W. W. Norton & Company. All rights reserved.

Chapter 15: Writing Large Programs Chapter 16: Structures, Unions, and Enumerations Defining Macros Outside a Program Structure Variables -U • Many compilers also support the option, which • The properti es of a stttructure are differentf t from “undefines” a macro as if by using #undef. those of an array. • We can use -U to undefine a predefined macro or – The elements of a structure (its members) aren’t one that was defined earlier in the command line required to have the same type. using -D. – The memb ers of a st ruct ure h ave names; t o sel ect a particular member, we specify its name, not its position. • IlIn some languages, st ttlldructures are called records, and members are known as fields.

2 Copyright © 2008 W. W. Norton & Company. All rights reserved. 96 Copyright © 2008 W. W. Norton & Company. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Declaring Structure Variables Declaring Structure Variables • AtA struc ture i s a l ogi lhi choice f or st ori ng a • Abs tract represent ati ons of a st ruct ure: collection of related data items. • A declaration of two structure variables that store information about parts in a warehouse: struct { int number; • Member values will go in the boxes later. ch[har name[NAME_LEN+ 1]; int on_hand; } part1, part2;

3 Copyright © 2008 W. W. Norton & Company. 5 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Declaring Structure Variables Declaring Structure Variables • The memb ers of a st ruct ure are • EhtEach struct ure represent s a new scope. stored in memory in the order in • Any names declared in that scope won’t conflict whichth h they’ re d ecl ared . with other names in a program. • Appearance of part1 • In C terminology, each structure has a se parate • Assumptions: name space for its members. – part1 is located at address 2000. – Integers occupy four bytes. – NAME_ LEN has the value 25. – There are no gaps between the members.

4 Copyright © 2008 W. W. Norton & Company. 6 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Declaring Structure Variables Initializing Structure Variables • FlthfllidltiFor example, the following declarations can • Struc ture i niti ali zers f oll ow rul es si mil t o th ose appear in the same program: for array initializers. struct { • Expressions used in a structure initializer must be int number; constant. (This restriction is relaxed in C99.) char name[NAME_ LEN+1]; int on_hand; • An initializer can have fewer members than the } part1, part2; structure it’s initializing. struct { • Any “leftover” members are given 0 as their initial char name[NAME_LEN+1]; value. int number; char sex; } employee1, employee2;

7 Copyright © 2008 W. W. Norton & Company. 9 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Initializing Structure Variables Designated Initializers (C99) • A s truc ture d ecl arati on may i ncl ldude an i iitilinitializer: • C99’s des igna te ddi in itiali zers can b e used with struct { structures. int number; part1 char name[NAME_LEN+1]; • The i niti ali zer f or shithihown in the previous int on_hand; example: } part1 = {528, "Disk drive", 10}, {528, "Disk die"drive", 10} part2 = {914, "Printer cable", 5}; • In a designated initializer, each value would be labeled •Appearance of part1 after initialization: by the name of the member that it initializes: {.number = 528, .name = "Disk drive", .on_hand = 10} • The combination of the period and the member name is called a designator.

8 Copyright © 2008 W. W. Norton & Company. 10 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Designated Initializers (C99) Operations on Structures • Des igna te ddi in itia lizers are eas ier to rea d an d c hec k • To access a memb er withi n a st ruct ure, we writ e for correctness. the name of the structure first, then a period, then • Also, values in a designated initializer don’t have the name ofth f the memb er. to be placed in the same order that the members • Statements that display the values of part1’s are listed in the structure. members: – The programmer doesn’t have to remember the order in printf("Part number: %d\n", part1.number); which the members were originally declared. prif(intf("Part name: %s\n", part1)1.name); printf("Quantity on hand: %d\n", part1.on_hand); – The order of the members can be changed in the future wihithout aff ecti ng d esi gnatedi ni iitiali zers.

11 Copyright © 2008 W. W. Norton & Company. 13 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Designated Initializers (C99) Operations on Structures • No t a ll va lues list edi d in a d esi gnat edi d initi ali zer • The memb ers of a st ruct ure are l val ues. need be prefixed by a designator. • They can appear on the left side of an assignment •Example: or as the operand in an increment or decrement {.number = 528, "Disk drive", .on_hand = 10} expression: The compiler assumes that "Disk drive" part1.number = 258; initializes the member that follows number in the /* changes part1's part number */ part1. on_ hand++; structure. /* increments part1's quantity on hand */ • Any members that the initializer fails to account for are set to zero.

12 Copyright © 2008 W. W. Norton & Company. 14 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Operations on Structures Operations on Structures • The peri usedt d to access a st ruct ure memb er i s • A’tbidithArrays can’t be copied using the = operatbttor, but an actually a C operator. array embedded within a structure is copied when • It takes precedence over nearly all other operators. the encl osi ng st ruct ure i s copi . •Example: • Some programmers exploit this property by scanf("%d", &part1.on_hand); creating “dummy” structures to enclose arrays that The . operator takes precedence over the & will be copied later: operator, so & computes the address of struct { int a[10]; } a1, a2; a1 = a2; part1.on_ hand. /* legal, since a1 and a2 are structures */

15 Copyright © 2008 W. W. Norton & Company. 17 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Operations on Structures Operations on Structures • The oth er maj or st ruct ure operati on i s assi gnment : • The = operator can b e used onl y with st ruct ures of part2 = part1; compatible types. • The effect of this statement is to copy • Two structures declared at the same time (as part1.number into part2.number, part1 and part2 were) are compatible. part1.name into part2.name, and so on. • Structures declared using the same “structure tag” or the same type name are also comp atible. • Other than assignment, C provides no operations on entire structures. • In particular, the == and != operators can’t be used with structures.

16 Copyright © 2008 W. W. Norton & Company. 18 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Structure Types Declaring a Structure Tag • SthtSuppose that a program need dtdlls to declare several • The part tbdtdlibltag can be usedto declare variables: structure variables with identical members. struct part part1, part2; • We need a name that represents a type of structure, • We can’t drop the word struct: not a particular structure variable. part part1, part2; /*** WRONG ***/ • Ways to name a structure: part isn’t a type name; without the word – Declare a “structure tag” struct,,g it is meaningless. –Use typedef to define a type name • Since structure tags aren’t recognized unless preceded by the word struct, they don’t conflict with other names used in a program.

19 Copyright © 2008 W. W. Norton & Company. 21 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Declaring a Structure Tag Declaring a Structure Tag • A stttructure t ag idtidtifis a name usedto identify a • The d ecl arati on of a st ruct ure tag can bbidbe combined particular kind of structure. with the declaration of structure variables: • The declaration of a structure tag named part: struct part { struct part { int number; int number; char name[NAME_ LEN+1]; char name[NAME_LEN+1]; int on_hand; int on_hand; }part1 ,part2 ; }; • Note that a semicolon must follow the right brace.

20 Copyright © 2008 W. W. Norton & Company. 22 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Declaring a Structure Tag Defining a Structure Type • All st ruct ures d ecl aredt d to h ave t ype stttruct • When it comes ti me t o name a st ruct ure, we can part are compatible with one another: usually choose either to declare a structure tag or struct part part1 = {528, "Disk drive", 10}; to use tdftypedef. struct part part2; • However, declaring a structure tag is mandatory part2 = part1; when the structure is to be used in a linked list /* legal; both parts have the same type */ (Chapter 17).

23 Copyright © 2008 W. W. Norton & Company. 25 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Defining a Structure Type Structures as Arguments and Return Values • AlttitdlitttAs an alternative to declaring a structure tag, we • FtiFunctions may h ave st ttructures as argument tds and can use typedef to define a genuine type name. return values. • A definition of a type named Part: • A function with a structure argument: typedef struct { void print_part(struct part p) int number; { char name[NAME_LEN+1]; printf("Part number: %d\n", p.number); int on_hand; pp(rintf("Part name: %s\n",p.name ); printf("Quantity on hand: %d\n", p.on_hand); } Part; } • Part can be used in the same way as the built-in • A call of print_part: types: print_part(part1); PtPart par t1, par t2;

24 Copyright © 2008 W. W. Norton & Company. 26 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Structures as Arguments and Return Values Structures as Arguments and Return Values • AAf func tion th at ret urns a part stttructure: • There are o ther reasons t o avoid copyi ing st ruct ures. struct part build_part(int number, • For example, the header defines a const char *name , type named FILE, whichi h is typi cally ll a structure. int on_hand) { • Each FILE structure stores information about the struct part p; state of an open file and therefore must be unique in p.number = number; a program. strcpy(p.name , name); p.on_hand = on_hand; • Every function in that opens a file return p; returns a pointer to a FILE structure. } • A call of build_part: • Every function that performs an operation on an open file requires a FILE pointer as an argument. part1 = build_ part(528, "Disk drive", 10);

27 Copyright © 2008 W. W. Norton & Company. 29 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Structures as Arguments and Return Values Structures as Arguments and Return Values • PiPassing a st ttructure t o a f uncti tidtion and returning a • Within a f uncti on, th e i niti a lizer f or a st ruct ure structure from a function both require making a variable can be another structure: copy ofllf all memb ers i ithtn the struct ure. void f(struct part part1) • To avoid this overhead, it’s sometimes advisable { to pass a pointer to a structure or return a pointer struct part part2 = part1; … to a structure. } • Chapter 17 gives examples of functions that have • The structure being initialized must have a ppgointer to a structure as an argument and/or automatic storage duration. return a pointer to a structure.

28 Copyright © 2008 W. W. Norton & Company. 30 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Compound Literals (C99) Compound Literals (C99) • Chapt er 9i 9 int rod ucedth d the C99 feat ure k nown as th e • A compoun d literal may cont ai n d esi gnat ors, j ust compound literal. like a designated initializer: • A compound literal can be used to create a print_part((struct part) {.on_hand = 10, .name = "Disk drive", structure “on the fly,” without first storing it in a ..ubenumber=52 8}); variable. • A compound literal may fail to provide full • The resultinggp structure can be passed as a initialization, in which case any uninitialized parameter, returned by a function, or assigned to a members default to zero. variable.

31 Copyright © 2008 W. W. Norton & Company. 33 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Compound Literals (C99) Nested Arrays and Structures • A compoun d literal can b e usedt d to creat e a • Struc tures an d arrays can b e combi ned with out structure that will be passed to a function: restriction. pritint_par t((t(struc tpart) {528, "Dis k didrive ", 10}); • Arrays may have structures as their elements, and The compound literal is shown in bold. structures may contain arrays and structures as • AdlillbidiblA compoundliteral can also be assigned to a variable: members. part1 = (struct part) {528, "Disk drive", 10}; • AdlilifihiA compoundliteral consists of a type name within parentheses, followed by a set of values in braces. • When a compound literal represents a structure, the type name can be a structure tag preceded by the word stttruct or a tdftypedef name.

32 Copyright © 2008 W. W. Norton & Company. 34 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Nested Structures Nested Structures • Nes ting one st ruct ure i nsid e anoth er i s oft en • HiHaving name bttbe a structure mak kititttes it easier to treat useful. names as units of data. • Suppose that person_name is the following • AAf func tion th atdi t displ ays a name could be passed one structure: person_name argument instead of three arguments: struct person_name { disp lay_name (s tu den t1.name ); char first[FIRST_NAME_LEN+1]; • Copying the information from a person_name char m iddle_ in it ia l; structure to the name member of a student structure char last[LAST_NAME_LEN+1]; would take one assignment instead of three: }; stttruct person_name new_name; … student1.name = new_ name;

35 Copyright © 2008 W. W. Norton & Company. 37 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Nested Structures Arrays of Structures • We can use person_name as partft of a l arger • OfthtOne ofthe most common com bitifbinations of arrays structure: and structures is an array whose elements are struct student { stttructures. struct person_name name; • This kind of array can serve as a simple database. int id, age; char sex; • An array of part structures capable of storing }},; student1, student2; information about 100 parts: • Accessing student1’s first name, middle initial, struct part inventory[100]; or last name requires two applications of the . operator: strcpy(student1. name. first, "Fred" );

36 Copyright © 2008 W. W. Norton & Company. 38 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Arrays of Structures Initializing an Array of Structures • AiAccessing a par tithidbitin the arrayis done by using • One reason for in itia liz ing an array o f s truc tures is subscripting: that it contains information that won’t change prin t_par t(inven tory [i]); diduring program executi on. • Accessing a member within a part structure • Example: an array that contains country codes requibitifbitidbires a combination of subscripting and member used when making international telephone calls. selection: • The elements of the array will be structures that it[i]b883inventory[i].number = 883; store the name of a country along with its code: • Accessing a single character in a part name requires struct dialing_code { subiiflldblibscripting, followedby selection, f flldbollowedby char *country; subscripting: int code; i[i][0]'inventory[i].name[0] = '\0'; };

39 Copyright © 2008 W. W. Norton & Company. 41 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Initializing an Array of Structures Initializing an Array of Structures const struct dialing_ code country_ codes[] = • In itiali zi ng an array of st ruct ures i s d one i n much {{"Argentina", 54}, {"Bangladesh", 880}, the same way as initializing a multidimensional {"Brazil", 55}, {"Burma (Myanmar)", 95}, {"China", 86}, {"Colombia", 57}, array. {"Congo, Dem. Rep. of", 243}, {"Egypt", 20}, {"Ethiopia", 251}, {"France", 33}, • Each structure has its own brace-enclosed {"Germany", 49}, {"India", 91}, {"In dones ia ", 62}, {"Iran ", 98}, initializer; the array initializer wraps another set of {"Italy", 39}, {"Japan", 81}, braces around the structure initializers. {"Mexico", 52}, {"Nigeria", 234}, {" Pakistan" , 92}, {"Philippines ", 63}, {"Poland", 48}, {"Russia", 7}, {"South Africa", 27}, {"South Korea", 82}, {"Spain", 34}, {"Sudan", 249}, {"Thailand", 66}, {"Turkey", 90}, {"Ukraine", 380}, {"United Kingdom", 44}, {"United States", 1}, {"Vietnam", 84}}; • The inner braces around each structure value are optional.

40 Copyright © 2008 W. W. Norton & Company. 42 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Initializing an Array of Structures Program: Maintaining a Parts Database • C99’s des igna te ddi in itia lizers all ow an it em t o h ave • OtiOperations support tdbthedby the program: more than one designator. – Add a new part number, part name, and initial quantity • A declaration of the inventory array that uses a on hdhand designated initializer to create a single part: – Given a part number, print the name of the part and the current quantity on hand struct part inventory[100] = {[0].number = 528, [0].on_hand = 10, – Given a part number, change the quantity on hand [0].name[0] = ' \0'}; – Print a table showing all information in the database The first two items in the initializer use two – Terminate program execution designators; the last item uses three.

43 Copyright © 2008 W. W. Norton & Company. 45 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Program: Maintaining a Parts Database Program: Maintaining a Parts Database • The itinventory.c program illust rat es h ow • The cod es i (inser t), s (h)(search), u (dt)(update), p (it)(print), nested arrays and structures are used in practice. and q (quit) will be used to represent these operations. • The program tracks parts stored in a warehouse. • A sess ion w ith the program: Enter operation code: i • Information about the ppyarts is stored in an array of Enter part number: 528 structures. Enter part name: Disk drive Enter quantity on hand: 10 • Contents of each structure: – Part number Enter operation code: s Enter part number: 528 – Name Part name: Disk drive – Quantity Quantity on hand: 10

44 Copyright © 2008 W. W. Norton & Company. 46 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Program: Maintaining a Parts Database Program: Maintaining a Parts Database Enter operation code: s Enter part number: 914 • The program will st ore i nf ormati on ab out each Part not found. part in a structure.

Enter operation code: i • The structures will be stored in an array named Enter part number: 914 inventory. Enter part name: Printer cable Enter quantity on hand: 5 • A variable named num_parts will keep track of the number of ppyarts currently stored in the array . Enter operation code: u Enter part number: 528 Enter changgqe in quantit y on hand: -2

47 Copyright © 2008 W. W. Norton & Company. 49 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Program: Maintaining a Parts Database Program: Maintaining a Parts Database Enter operation code: s Enter part number: 528 • An ou tline ofth f the program’ s mai n l oop: Part name: Disk drive for (;;) { Quantity on hand: 8 promptttt user to enter operati tidon code; read code; Enter operation code: p Part Number Part Name Quantity on Hand switch (code){ 528 Disk drive 8 case 'i': perform insert operation; break; 914 Printer cable 5 case 's': perform search operation; break; case 'u': perform update operation; break; Enter operation code: q case 'p': perform print operation; break; case '''q': terminate program; default: print error message; } }

48 Copyright © 2008 W. W. Norton & Company. 50 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations

/********************************************************** Program: Maintaining a Parts Database * main: Prompts the user to enter an operation code, * * then calls a function to perform the requested * • Separa te f uncti ons will perf orm th e i nsert , search , * action. Repeats until the user enters the * * command 'q'. Prints an error message if the user * update, and print operations. * enters an illegal code. * **********************************************************/ •Since th e f uncti ons will all need access to int main(void) inventory and num_parts, these variables will { char code; btlbe external. for (;;) { printf("Enter operation code: "); • The program is split into three files: scanf(" %c", &code); – inventory.c (the bulk of the program) while (getchar() != '\n') /* skips to end of line */ ; – readline.h (contains the prototype for the readlid_line fti)function) – readline.c (contains the definition of read_line)

51 Copyright © 2008 W. W. Norton & Company. 53 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations

swith(d){itch(code){ inventory.c case 'i': insert(); /* Maintains a parts database (array version) */ break; case ' s' : search(); #include break; #include "readline.h" case 'u': update(); #de fine NAME_ LEN 25 break; #define MAX_PARTS 100 case 'p': print(); break; struct part { case 'q': return 0; int number; default: printf("Illegal code\n"); char name[NAME_LEN+1]; } int on_hand; printf("\n"); } inventory[MAX_PARTS]; } int num_parts = 0; /* number of parts currently stored */ } int find_ part(int number); void insert(void); void search(void); void update(void); void print(void);

52 Copyright © 2008 W. W. Norton & Company. 54 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations

/********************************************************** prin tf("En ter par t num ber: "); * find_part: Looks up a part number in the inventory * scanf("%d", &part_number); * array. Returns the array index if the part * if (find_part(part_number) >= 0) { * number is found; otherwise, returns -1*1. * printf(" Part already exists.\nn);"); **********************************************************/ return; int find_part(int number) } { int i; inventory[num_parts].number = part_number; printf("Enter part name: "); for (i = 0; i < num_pp)arts; i++) read_ line((y[inventory[num_pp]arts].name , NAME_ LEN); if (inventory[i].number == number) printf("Enter quantity on hand: "); return i; scanf("%d", &inventory[num_parts].on_hand); return -1; num_parts++; } }

55 Copyright © 2008 W. W. Norton & Company. 57 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations

/********************************************************** /********************************************************** * insert: Prompts the user for information about a new * * search: Prompts the user to enter a part number, then * * part and then inserts the part into the * * looks up the part in the database. If the part * * database. Prints an error message and returns * * exists, prints the name and quantity on hand; * * prematurely if the part already exists or the * * if not, prints an error message. * * database is full. * **********************************************************/ **********************************************************/ void search(void) void insert(void) { { int i, number; int part_ number; printf("Enter part number: "); if (num_parts == MAX_PARTS) { scanf("%d", &number); printf("Database is full; can't add more parts.\n"); i = find_part(number); return; if (i >= 0) { } printf("Part name: %s\n", inventory[i].name); printf("Quantity on hand: %d\n", inventory[i].on_hand); } else printf("Part not found.\n"); }

56 Copyright © 2008 W. W. Norton & Company. 58 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations

/********************************************************** * update: Prompts the user to enter a part number. * Program: Maintaining a Parts Database * Prints an error message if the part doesn't * * exist; otherwise, prompts the user to enter * • The versi on of readlid_line iChtin Chapter 13 won’t * change in quantity on hand and updates the * * database. * work properly in the current program. **********************************************************/ void update(void) • Consider wh at h appens wh en th e user i nserts a part: { int i, number, change; Enter part number: 528 Enter part name: Dikdiiskdrive printf("Enter part number: "); scanf("%d", &number); • The user presses the Enter key after entering the part i = find_part(number); if (i >= 0) { numbliber, leaving an i iiiblnvisible new-line ch aracter th at printf("Enter change in quantity on hand: "); the program must read. scanf("%d " , &change); inventory[i].on_hand += change; • When scanf reads the part number, it consumes } else the 5, 2, and 8, but leaves the new-line character pp(rintf("Part not found.\n"); } unread.

59 Copyright © 2008 W. W. Norton & Company. 61 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations

/********************************************************** * print: Prints a listing of all parts in the database, * Program: Maintaining a Parts Database * showing the part number, part name, and * * quantity on hand. Parts are printed in the * • If we tryt to readth d the part name usi ngth the origi i inal * order in which they were entered into the * * database. * read_line function, it will encounter the new- **********************************************************/ void print(void) line character immediately and stop reading. { • This problem is common when numerical input is int i; fllfollowedby db ch aract er i nput . printf("Part Number Part Name " "Quantity on Hand\n"); • One solution is to write a version of read_line for (i = 0; i < num_parts; i++) that skips white-space characters before it begins printf("%7d %-25s%11d\n", inventory[i].number, inventory[i].name, inventory[i].on_hand); storing characters. } • This solves the new-line problem and also allows us to avoid storing blanks that precede the part name.

60 Copyright © 2008 W. W. Norton & Company. 62 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations readline.h Unions #ifndef READLINE_H #define READLINE_H • A union, like a st ruct ure, consi st s of one or more /********************************************************** members, possibly of different types. * rea d_ line: Skips lea ding w hite-space chtharacters, th*then * * reads the remainder of the input line and * • The compiler allocates only enough space for the * stores it in str. Truncates the line if its * largest of the members, which overlay each other * length exceeds n. Returns the number of * * characters stored. * within this space. **********************************************************/ int read_ line(char str[], int n); • Assigggning a new value to one member alters the values of the other members as well. #endif

63 Copyright © 2008 W. W. Norton & Company. 65 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations readline.c Unions #include #include • AlfiiblAn example of a union variable: #include "readline.h" union { itint rea dli(hd_line(char st t[]itr[], int n ) itiinti; { int ch, i = 0; double d; }u; while (isspace(ch = getchar())) ; • The declaration of a union closely resembles a while (ch !='\n' && ch != EOF) { structure declaration: if (i < n) str[i++] = ch; struct { ch = getchar(); int i; } str[i] = '\0'; double d; return i; } s; }

64 Copyright © 2008 W. W. Norton & Company. 66 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Unions Unions • The st ruct ure s andthe • The properti es of uni ons are al mostid t identi calt l to th e union u differ in just one properties of structures. way. • We can declare union tags and union types in the • The members of s are same way we declare structure tags and types. stored at different • Like structures, unions can be copied using the = addresses in memory. oppperator, passed to functions, and returned b y • The members of u are functions. stored at the same address.

67 Copyright © 2008 W. W. Norton & Company. 69 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Unions Unions • MbMembers o f a un ion are accesse dithdin the same way • OlOnly thfitthe first memb er of a uni on can b e gi ven an as members of a structure: initial value. u.i = 82; • How to initialize the i member of u to 0: u.d = 74.8; union { • Changing one member of a union alters any value int i; previously stored in any of the other members. double d; }}u u = {0}; – Storing a value in u.d causes any value previously stored in u.i to be lost. • The expression inside the braces must be constant. – Changing u.i corrupts u.d. (The rul es are sli ghtl y erenti t in C99 .)

68 Copyright © 2008 W. W. Norton & Company. 70 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Unions Using Unions to Save Space • Des igna tedi d initi a lizers can al so b e used with • UiUnions can be use dto save space i n st ruct ures. unions. • Suppose that we’re designing a structure that will • A designated initializer allows us to specify which contain information about an item that’s sold member of a union should be initialized: through a gift catalog. union { • Each item has a stock number and a price, as well int i; as other information that deppypends on the type of dblddouble d; the item: } u = {.d = 10.0}; Books: Title,,, author, number of pgpages • On ly one mem ber can be initi ali zed , b utitd t it doesn’t Mugs: Design have to be the first one. Shirts: Desigg,n, colors available , sizes available

71 Copyright © 2008 W. W. Norton & Company. 73 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Unions Using Unions to Save Space • AlitifApplications for uni ons: • Afirs t att empt atd esig ini ngth the catltalog_ item – Saving space structure: – Building mixed data structures struct catalilog_item { – Viewing storage in different ways (discussed in Chapter int stock_number; double price; 20) int item_type; char title[TITLE_LEN+1]; char author[AUTHOR_LEN+1]; int num_pages; char design[DESIGN_ LEN+1]; int colors; int sizes; };

72 Copyright © 2008 W. W. Norton & Company. 74 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Using Unions to Save Space Using Unions to Save Space • The item_ type membldhfthber would have one ofthe • If c is a catltalog_ item stttructure th thtat represent s values BOOK, MUG, or SHIRT. a book, we can print the book’s title in the •The colors and sizes members would store fllfollowi ng way: encoded combinations of colors and sizes. printf("%s", c.item.book.title); • This structure wastes space, since only part of the • As this example shows, accessing a union that’s information in the structure is common to all items nested inside a structure can be awkward. in the catalog. •Byputtin g a union inside the catalog_item structure, we can reduce the space required by the structure.

75 Copyright © 2008 W. W. Norton & Company. 77 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Using Unions to Save Space Using Unions to Save Space struct catalog_item { int stock_number; • The catltalog_ item stttructure can b e usedt o double price; int item_type; illustrate an interesting aspect of unions. union { struct { • Norma lly, it’ s not a goodid d idea t o st ore a val ue i nt o one char title[TITLE_LEN+1]; member of a union and then access the data through a char author[AUTHOR_LEN+1]; int num_pages; different member. } book; struct { • However, there is a special case: two or more of the char design[DESIGN_ LEN+1]; members of the union are structures, and the structures } mug; struct { begin with one or more matching members. char design[DESIGN_LEN+1]; int colors; • If one o ffth the s truct ures i s currentl y valid , th en th e int sizes; } shirt; matching members in the other structures will also be } item; valid. };

76 Copyright © 2008 W. W. Norton & Company. 78 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Using Unions to Save Space Using Unions to Build Mixed Data Structures • The uni on emb edd e ddi in th e catltalog_ item • NtNext, we creat e an array wh ose el ement s are structure contains three structures as members. Number values: • Tfth(Two ofthese (mug and shir t))b beg in with a Number number_array[1000]; matching member (design). •A Number union can store either an int value or • NhilfhNow, suppose that we assign a value to one of the a double value. design members: • This makes it possible to store a mixture of int strcpy(c.iiitem.mug.design, "Cats"); and double values in number_array: •The design member in the other structure will be number_ array[0 ].i = 5 ; dfiddefined andh ave th e same val ue: number_array[1].d = 8.395; printf("%s", c.item.shirt.design); /* prints " Cats" */

79 Copyright © 2008 W. W. Norton & Company. 81 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Using Unions to Build Mixed Data Structures Adding a “Tag Field” to a Union • UiUnions can b e use dto creat e d dtata st ruct ures th thtat • There’ s no easy way t o t tllell whi hihch memb er of a uni on was contain a mixture of data of different types. last changed and therefore contains a meaningful value. • Consider the problem of writing a function that displays • Suppose that we need an array whose elements are the value stored in a Number union: int double a mixture of and values. void print_ number(()Number n) • First, we define a union type whose members { if (n contains an integer) represent the different kinds of data to be stored in printf(" %d", n. i); the array: else typedef union { printf("%g", n.d); } int i; There’s no way for print_number to determine double d; whether n contains an integer or a floating-point number. } Number;

80 Copyright © 2008 W. W. Norton & Company. 82 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Adding a “Tag Field” to a Union Adding a “Tag Field” to a Union • IdtktkfthiiftiIn order to keep track of this information, we can • EhtiEachtime we assi gn a val ue t o a memb er of u, embed the union within a structure that has one we’ll also change kind to remind us which other memb er: a “t ag fi eld” or “di scri mi nant .” membfber of u we modified . • The purpose of a tag field is to remind us what’s • An example that assigns a value to the i member currently stored in the union. of u: • item_type served this purpose in the n.kind = INT_KIND; catalog_item structure. n.u.i = 82; n is assumed to be a Number variable.

83 Copyright © 2008 W. W. Norton & Company. 85 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Adding a “Tag Field” to a Union Adding a “Tag Field” to a Union • The NbNumber type as a structure with an embedded • When th e numb er st oredi d in a NbNumber varibliiable is union: retrieved, kind will tell us which member of the #define INT_ KIND 0 unithlttbidlion was the lastto be assigned a value. #define DOUBLE_KIND 1 • A function that takes advantage of this capability: typedef struct { int kind; /* tag field */ void print_number(Number n) union { { itiinti; if (n. kin d == INT_KIND ) double d; printf("%d", n.u.i); } u; else } Number; printf("%g", n.u.d); • The value of kind will be either INT_KIND or } DOUBLE_KIND.

84 Copyright © 2008 W. W. Norton & Company. 86 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Enumerations Enumerations • In many programs, we ’ll need vari abl es th ath t have • UiUsing macros to d dfiefine a suit it“t “type” and names only a small set of meaningful values. for the various suits is a step in the right direction: • A variable that stores the suit of a playing card #define SUIT int should have only four potential values: “clubs,” #define CLUBS 0 “diamonds,” “hearts,” and “spades.” #define DIAMONDS 1 #define HEARTS 2 #define SPADES 3 • An updated version of the previous example: SUIT s; … s = HEARTS;

87 Copyright © 2008 W. W. Norton & Company. 89 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Enumerations Enumerations • AA“ “suit” vari abl e can b e d ecl ared as an i nt eger, • Pro blems w ith this t ech ni que: with a set of codes that represent the possible – There’s no indication to someone reading the program valfthibllues ofthe variable: thatth t the macros represent val ues ofth f the same “t ype.” int s; /* s will store a suit */ – If the number of possible values is more than a few, … defining a separate macro for each will be tedious. s = 2; /* 2 represents "hearts" */ – The names CLUBS, DIAMONDS, HEARTS, and • Pro blems with this t ech ni que: SPADES will be removed by the preprocessor, so they won’t be available during debugging. – We can’t tell that s has only four possible values. – Thiifihe significance of fi 2 isn’t apparent.

88 Copyright © 2008 W. W. Norton & Company. 90 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Enumerations Enumerations • CidilkidftdidC provides a specialkind oftype designed • EtittiiltttEnumeration constants are similar to constants specifically for variables that have a small number created with the #define directive, but they’re ofibllf possible values. notiltt equivalent. •An enumerated type is a type whose values are • If an enumeration is declared inside a function, its listed (“enumerated”) by the programmer. constants won’t be visible outside the function. • Each value must have a name (an enumeration constant).

91 Copyright © 2008 W. W. Norton & Company. 93 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Enumerations Enumeration Tags and Type Names • Although enumerati ons h ave littl e i n common • As w ith st ruct ures and uni ons, th ere are t wo ways with structures and unions, they’re declared in a to name an enumeration: by declaring a tag or by siilimilar way: using tdftypedef ttto create a genui itne type name. enum {CLUBS, DIAMONDS, HEARTS, SPADES} s1, s2; • Enumeration tags resemble structure and union • The names of enumeration constants must be tags: different from other identifiers declared in the enum suit {CLUBS, DIAMONDS, HEARTS, SPADES}; enclosing scope. • suit variables would be declared in the following way: enum suit s1, s2;

92 Copyright © 2008 W. W. Norton & Company. 94 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Enumeration Tags and Type Names Enumerations as Integers • AlttildAs an alternative, we could use tdftypedef tkto make • The programmer can ch oose diff eren t va lues f or Suit a type name: enumeration constants: typedef enum {CLUBS, DIAMONDS, HEARTS, SPADES} Suit; enum suit {CLUBS = 1, DIAMONDS = 2, Suit s1, s2; HEARTS = 3, SPADES = 4}; • In C89, using typedef to name an enumeration •Thlhe values of enumerati on constants may b e is an excellent way to create a Boolean type: arbitrary integers, listed in no particular order: typedef enum {FALSE, TRUE} Bool; enum dept {RESEARCH = 20, PRODUCTION = 10, SALES = 25}; • It’s even legal for two or more enumeration constants to have the same value.

95 Copyright © 2008 W. W. Norton & Company. 97 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Enumerations as Integers Enumerations as Integers • BhidthBehindthe scenes, Ct reat s enumerati on vari iblables • When no val ue i s specifi edf d for an enumerati on and constants as integers. constant, its value is one greater than the value of • By default, the compiler assigns the integers 0, 1, the previ ous const ant . 2, … to the constants in a particular enumeration. • The first enumeration constant has the value 0 by •In the suit enumeration, CLUBS, DIAMONDS, default. HEARTS, and SPADES represent 0, 1, 2, and 3, •Example: respectively. enum EGA_colors {BLACK, LT_GRAY = 7, DK_GRAY, WHITE = 15}; BLACK has the value 0, LT_GRAY is 7, DK_GRAY is 8, and WHITE is 15.

96 Copyright © 2008 W. W. Norton & Company. 98 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Enumerations as Integers Using Enumerations to Declare “Tag Fields” • Enumerati on val ues can b e mi xed with ordi nary • EtiftfdtiihihEnumerations are perfectfor determining which integers: member of a union was the last to be assigned a iiint i; value. enum {CLUBS, DIAMONDS, HEARTS, SPADES} s; •In the Number structure, we can make the kind i = DIAMONDS; /* i is now 1 */ member an enumeration instead of an int: s = 0; /* s is now 0 (CLUBS) */ typedef struct { s++; /* s is now 1 (DIAMONDS) */ enum {}kid{INT_KIND, DOUBLE_KIND}kind; i = s + 2; /* i is now 3 */ union { • s is treated as a variable of some integer type. int i; double d; • CLUBS, DIAMONDS, HEARTS, and SPADES are } u; namesfortheintegers012and3names for the integers 0, 1, 2, and 3. } Number;

99 Copyright © 2008 W. W. Norton & Company. 101 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 16: Structures, Unions, and Enumerations Chapter 16: Structures, Unions, and Enumerations Enumerations as Integers Using Enumerations to Declare “Tag Fields” • Although it’s conveni entt t to b e abl e t o use an • The new st ruct ure i s usedi d in exactl y th e same way enumeration value as an integer, it’s dangerous to as the old one. use an itinteger as an enumerati on val ue. • Advantages of the new structure: • For example, we might accidentally store the – Does away with the INT_KIND and DOUBLE_KIND number 4—which doesn’t correspond to any macros suit—into s. – Makes it obvious that kind has only two possible values: INT_ KIND and DOUBLE_ KIND

100 Copyright © 2008 W. W. Norton & Company. 102 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Dynamic Storage Allocation • DitlltiidtftfDynamic storage allocation is used most often for strings, arrays, and structures. Chapter 17 • Dynamically allocated structures can be linked together to form lists, trees, and other data structures. Advanced Uses of Pointers •Dyygnamic storage allocation is done by yg calling a memory allocation function.

1 Copyright © 2008 W. W. Norton & Company. 3 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Dynamic Storage Allocation Memory Allocation Functions • C’s d at a st ruct ures, i ncl udi ng arrays, are normall y • The hdheader dldeclares th ree memory fixed in size. allocation functions: •Fixed-size data structures can be a problem, since malloc—Allocates a bl ock of memory b ut d oesn’ t we’re forced to choose their sizes when writing a initialize it. program. calloc—Allocat es a bl ock of memory and cl ears it . realloc—Resizes a previously allocated block of • Fortunatelyypp, C supports dyygnamic storage memory. allocation: the ability to allocate storage during • These functions return a value of type void * (a ppgrogram execution. “i”it)“generic” pointer). • Using dynamic storage allocation, we can design data structures that grow (and shrink) as needed.

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Null Pointers Null Pointers • If a memory a llocati on f uncti on can’t locat e a • PitPointers t estt rue or f flalse i n th e same way as numb ers. memory block of the requested size, it returns a • All non-null pointers test true; only null pointers are null poi nt er. flfalse. • A null pointer is a special value that can be • Instead of writing distinguished from all valid pointers. if (p == NULL) … • After we’ve stored the function’s return value in a we could write pointer variable, we must test to see if it’s a null if (!p) … pointer. • Instead of writing if (p != NULL) … we could write if (p) …

5 Copyright © 2008 W. W. Norton & Company. 7 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Null Pointers Dynamically Allocated Strings • AlfttiAn example oftesting malloc’t’s return val ue: • DitlltiiftflfDynamic storage allocation is often usefulfor p = malloc(10000); working with strings. if (p == NULL) { /* allocation failed; take appropriate action */ • Strings are stored in character arrays, and it can be } hard to anticipate how long these arrays need to • NULL is a macro (defined in various library be. headers) that represents the null pointer. •Byyggyy allocating strings dynamically, we can • Some programmers combine the call of malloc postpone the decision until the program is running. with the NULL test: if ((p = malloc(10000)) == NULL) { /* allocation failed; take appropriate action */ }

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Using malloc to Allocate Memory for a String Using malloc to Allocate Memory for a String • PttPrototype f or th e malloc ftifunction: • MlltdiMemory allocated using malloc i’tlisn’t cleared , so void *malloc(size_t size); p will point to an uninitialized array of n + 1 • malloc allocates a block of size bytes and chtharacters: returns a pointer to it. • size_t is an unsigned integer type defined in the library.

9 Copyright © 2008 W. W. Norton & Company. 11 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Using malloc to Allocate Memory for a String Using malloc to Allocate Memory for a String • AllfA call of malloc that all ocat es memory f or a • Ca lling strcpy is one way t o i niti a lize thi s array: string of n characters: strcpy(p, "abc"); p = malloc(n + 1); • The first four characters in the array will now be p is a char * variable. a, b, c, and \0: • Each character requires one byte of memory; adding 1 to n leaves room for the null character. • Some programmers prefer to cast malloc’s return value, although the cast is not required: p = (char *) malloc(n + 1);

10 Copyright © 2008 W. W. Norton & Company. 12 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Using Dynamic Storage Allocation Using Dynamic Storage Allocation in String Functions in String Functions • Dynamic storage allocation makes it possible to • A call of the concat function: write functions that return a pointer to a “new” p = concat("abc", "def"); string. • After the call, p will point to the string • Consider the ppgroblem of writing a function that "abcdef", which is stored in a dynamically concatenates two strings without changing either allocated array. one. • The function will measure the lengths of the two stringg,s to be concatenated, then call malloc to allocate the right amount of space for the result.

13 Copyright © 2008 W. W. Norton & Company. 15 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Using Dynamic Storage Allocation Using Dynamic Storage Allocation in String Functions in String Functions char *conca t(tht(const char *1*s1, cons tht char *2)*s2) • Functions such as concat that dynamically { char *result; allocate storage must be used with care. result = malloc(strlen(s1) + strlen(s2) + 1); • When the string that concat returns is no longer if (result == NULL) { needed, we’ll want to call the free function to printf("Error: malloc failed in concat\n"); release the space that the string occupies. exit(EXIT_FAILURE); } • If we don’ t, the program may eventually run out of strcpy(result, s1); memory. strcat(result, s2); return result; }

14 Copyright © 2008 W. W. Norton & Company. 16 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Program: Printing a One-Month remind2.c Reminder List (Revisited) /* Prints a one-month reminder list (dynamic string version) */ •The remind2.c program is based on the #include remind.c program of Chapter 13, which prints a #include one-month list of daily reminders. #ild#include < • The original remind.c program stores reminder #define MAX_REMIND 50 /* maximum number of reminders */ #define MSG_LEN 60 /* max length of reminder message * / strings in a two-dimensional array of characters. int read_line(char str[], int n); • In the new program, the array will be one- int main(void) { dimensional; its elements will be pointers to char *reminders[MAX_REMIND]; dynamically allocated strings. char day_str[3], msg__str[MSG LEN+1]; int day, i, j, num_remind = 0;

17 Copyright © 2008 W. W. Norton & Company. 19 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Program: Printing a One-Month f(){for (;;){ if (num_remind == MAX_REMIND) { Reminder List (Revisited) printf("-- No space left --\n"); break; • Advantages of switching to dynamically allocated } strings: printf(" Enter day and reminder:" ); – Uses space more efficiently by allocating the exact scanf("%2d", &day); number of characters needed to store a reminder. if (day == 0) break; – Avoids calling strcpy to move existing reminder sprintf(day_str, "%2d", day); strings in order to make room for a new reminder. read_line(msg_str, MSG_LEN); • Switching from a two-dimensional array to an for (i = 0; i < num_remind; i++) if (strcmp(day_str, reminders[i]) < 0) array of pointers requires changing only eight break; lines of the program (shown in bold). for (j = num_remind; j > i; j--) reminders[j] = reminders[j-1];

18 Copyright © 2008 W. W. Norton & Company. 20 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers

remin ders [i] = mall oc (2 + s len (msg_s tr ))+1) + 1); if (reminders[i] == NULL) { Dynamically Allocated Arrays printf("-- No space left --\n"); break; } • DilllltdhthDynamically allocated arrays have the same advantages as dynamically allocated strings. strcpy(reminders[i], day_ str); strcat(reminders[i], msg_str); • The close relationship between arrays and pointers

num_ remind++; makes a dynamically allocated array as easy to use } as an ordinary array. printf("\nDay Reminder\n"); • Although malloc can allocate space for an array, for (i = 0; i < num_remind; i++) printf(" %s\n", reminders[i]); the calloc function is sometimes used instead, since it initializes the memory that it allocates. return 0; } •The realloc function allows us to make an array “grow ” or“ shrink” as needed.

21 Copyright © 2008 W. W. Norton & Company. 23 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers itint rea dli(hd_line(char st t[]itr[], int n ) { Using malloc to Allocate Storage for an Array int ch, i = 0; • SdfSuppose a program needs an array of n itintegers, while ((ch = getchar()) != '\n') if (i < n) where n is computed during program execution. str[i++] = ch; str[i] = '\0'; • We’ll first declare a pointer variable: return i; } int *a; • Once the value of n is known, the program can call malloc to allocate sppyace for the array: a = malloc(n * sizeof(int)); • Always use the sizeof operator to calculate the amount of space required for each element.

22 Copyright © 2008 W. W. Norton & Company. 24 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Using malloc to Allocate Storage for an Array The calloc Function • We can now i gnore th e f actth t that a iitdis a pointer and • AllfA call of calloc that all ocat es space f or an array use it instead as an array name, thanks to the of n integers: reltilationshi hibtp between arrays and poi itnters i n C . a = calloc(n, sizeof(int)); • For example, we could use the following loop to • By calling calloc with 1 as its first argument, initialize the array that a points to: we can allocate space for a data item of any type: for (i = 0; i < n; i++) struct point { int x, y; } *p; a[i] = 0; p = calloc(1, sizeof(struct point)); • We also have the option of using pointer arithmetic instead of subscripting to access the elements of the array.

25 Copyright © 2008 W. W. Norton & Company. 27 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers The calloc Function The realloc Function • The calloc ftiifunction is an alt lttiternative to • The realloc ftifunction can resi ze a d ynami illcally malloc. allocated array. • Prototype for calloc: • Prototype for realloc: void *calloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); • Properties of calloc: • ptr must point to a memory block obtained by a – Allocates sppyace for an array with nmemb elements, previous call of malloc, calloc, or realloc. each of which is size bytes long. • size represents the new size of the block, which – Returns a null pointer if the requested space isn’t may be larger or smaller than the original size. available. – Initializes allocated memory by setting all bits to 0.

26 Copyright © 2008 W. W. Norton & Company. 28 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers The realloc Function Deallocating Storage • PtifProperties of realloc: •malloc andthe oth er memory all ocati on – When it expands a memory block, realloc doesn’t functions obtain memory blocks from a storage initi a lize th e b yt es th at are add edt d to th e bl ock . poolknown as th e heap. – If realloc can’t enlarge the memory block as • Calling these functions too often—or asking them requested, it returns a null pointer; the data in the old for large blocks of memory—can exhaust the memory block is unchanged. heap, causing the functions to return a null pointer. – If realloc is called with a null pointer as its first argument, it behaves like malloc. • To make matters worse, a program may allocate – If realloc is called with 0 as its second argg,ument, it blocks of memory and then lose track of them, frees the memory block. thereby wasting space.

29 Copyright © 2008 W. W. Norton & Company. 31 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers The realloc Function Deallocating Storage • WtWe expect realloc to b e reasonably bl effi ci ent : • ElExample: – When asked to reduce the size of a memory block, p = malloc(…); realloc should shrink the block“ in place.” q = malloc (… ); – realloc should always attempt to a memory p = q; block without moving it. • AhtftthfittttthbA snapshot after the firsttwo statements have been • If it can’t enlarge a block, realloc will allocate a executed: new block elsewhere, then copy the contents of the old block into the new one. • Once realloc has returned, be sure to update all pointers to the memory block in case it has been moved.

30 Copyright © 2008 W. W. Norton & Company. 32 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Deallocating Storage The free Function • After q iidtis assignedto p, bthboth var ibliables now poi itnt • PttPrototype f or free: to the second memory block: void free(void *ptr); • free will be passed a pointer to an unneeded memory block: p = malloc(…); q = malloc(…); • There are no pointers to the first block, so we’ll free(p); never be able to use it again. p = q; • Ca lling free relthblkfthtleases the block of memory that p points to.

33 Copyright © 2008 W. W. Norton & Company. 35 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Deallocating Storage The “Dangling Pointer” Problem • Ablock of memory th tht’at’s no l onger accessibl e t o • UiUsing free ldtleads to a new probl em: dlidangling a program is said to be garbage. pointers. • A program that leaves garbage behind has a • f()free(p) dlltdeallocates th e memory bl blkthtockthat p poitints memory leak. to, but doesn’t change p itself. p • Some languages provide a garbage collector that • If we forge ttth that no longer poi nt s t o a valid memory block, chaos may ensue: automaticallyyygg locates and recycles garbage, but C char *p = ma lloc (4); doesn’t. … free(p); • Instead, each C program is responsible for … recycling its own garbage by calling the free strcpy(p, "abc"); /*** WRONG ***/ function to release unneeded memory. • Modifying the memory that p points to is a serious error. 34 Copyright © 2008 W. W. Norton & Company. 36 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers The “Dangling Pointer” Problem Linked Lists • DliitDangling pointers can b bhdttie hardto spot, since • AlikAlinkedli dlitistis more fl exibl e th an an array: we can several pointers may point to the same block of easily insert and delete nodes in a linked list, memory. allowi ng th e li stt t to grow and sh ri nk as need ed . • When the block is freed, all the pointers are left • On the other hand, we lose the “random access” dangling. capability of an array: – Any element of an array can be accessed in the same amount of time. – Accessing a node in a linked list is fast if the node is clhbiifhlilifi’hlose to the beginning of the list, slow if it’s near the end.

37 Copyright © 2008 W. W. Norton & Company. 39 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Linked Lists Declaring a Node Type • DitlltiiillflfDynamic storage allocation is especially usefulfor • To set up a li nk edli d list , we’ll need a st ruct ure th at building lists, trees, graphs, and other linked data represents a single node. stttructures. • A node structure will contain data (an integer in this •A linked list consists of a chain of structures example) plus a pointer to the next node in the list: (called nodes), with each node containing a struct node { int value; /* data stored in the node */ pointer to the next node in the chain: struct node *next; /* pointer to the next node */ }; • node must be a tag, not a typedef name, or there next • The last node in the list contains a null pointer. would be no way to declare the type of .

38 Copyright © 2008 W. W. Norton & Company. 40 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Declaring a Node Type Creating a Node • NtNext, we’ll ’lld need a vari iblthtlable that always poi ittnts to • When we creat e a nod e, we’ll need a vari abl e th at the first node in the list: can point to the node temporarily: struct node *first = NULL; struct node *new_node; • Setting first to NULL indicates that the list is • We’ll use malloc to allocate memory for the initially empty. new node, saving the return value in new_node: new_node = malloc(sizeof(struct node)); • new_node now points to a block of memory just larggge enough to hold a node structure:

41 Copyright © 2008 W. W. Norton & Company. 43 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Creating a Node Creating a Node • Attlikdlit’lltdAs we construct a linkedlist, we’ll create nodes • NtNext, we’ll ’llt store d dtithata in the value membfber of one by one, adding each to the list. the new node: • Steps involved in creating a node: (*new_node).value = 10; 1. Allocate memory for the node. • The resulting picture: 2. Store data in the node. 3. Insert the node into the list. • We’ll concentrate on the first two steps for now. • The parentheses around *new_node are mandatory because the . operator would otherwise take precedence over the * operator.

42 Copyright © 2008 W. W. Norton & Company. 44 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Inserting a Node at the The -> Operator Beginning of a Linked List • AiAccessing a memb bfttier of a structure using a poi itnter • One of the advantages of a linked list is that nodes is so common that C provides a special operator can be added at any point in the list. fthifor this purpose. • However, the beginning of a list is the easiest • This operator, known as right arrow selection, is a place to insert a node. minus sign followed by >. • Suppose that new_node is pointing to the node • Using the -> operator, we can write to be inserted, and first is ppgointing to the first new_node->value = 10; node in the linked list. instead of (*new_node).value = 10;

45 Copyright © 2008 W. W. Norton & Company. 47 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Inserting a Node at the The -> Operator Beginning of a Linked List • The -> operatdtor produces an l llvalue, so we can use • It takes two statements to insert the node into the it wherever an ordinary variable would be list. allowed . • The first step is to modify the new node’s next •A scanf example: member to pppyoint to the node that was previously at scanf("%d", &new_node->value); the beginning of the list: •The & oppqerator is still required, even thou gh new_ node->next = first; new_node is a pointer. • The second step is to make first point to the new node: first = new_node; • These statements work even if the list is empty.

46 Copyright © 2008 W. W. Norton & Company. 48 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Inserting a Node at the Inserting a Node at the Beginning of a Linked List Beginning of a Linked List • Let’s trace the process of inserting two nodes into new_node->next = first; an empty list. • We’ll insert a node containing the number 10 first,

followed byyg a node containing 20. first = new_ node;

new_ node = malloc(sizeof(struct node));

49 Copyright © 2008 W. W. Norton & Company. 51 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Inserting a Node at the Inserting a Node at the Beginning of a Linked List Beginning of a Linked List first = NULL; new_node->val20lue = 20;

new_ node = new_ node->next = first; malloc(sizeof(struct node));

new_ node->value = 10; first = new_ node;

50 Copyright © 2008 W. W. Norton & Company. 52 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Inserting a Node at the Inserting a Node at the Beginning of a Linked List Beginning of a Linked List • A function that inserts a node containing n into a • A function that uses add_to_list to create a linked linked list, which pointed to by list: list containing numbers entered by the user: struct node *add_to_list(struct node *list, int n) struct node *read_numbers(void) { { struct node *new_node; struct node *first = NULL; int n; new_node = malloc(sizeof(struct node)); printf("Enter a series of integers (0 to terminate): "); if (new_node == NULL) { for (;;) { printf("Error: malloc failed in add_ to_ list\nn);"); scanf("%d", &n); exit(EXIT_FAILURE); if (n == 0) } return first; new_node ->value = n; firs t = a dd_ to_ lis t(firs t, n ); new_node->next = list; } return new_node; } } • The numb ers will be i n reverse ord er withi n th e li st .

53 Copyright © 2008 W. W. Norton & Company. 55 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Inserting a Node at the Searching a Linked List Beginning of a Linked List • Note that add_to_list returns a pointer to the • Although a while lbdthloop can be usedto search a newly created node (now at the beginning of the list, the for statement is often superior. list). • A loop that visits the nodes in a linked list, using a • When we call add___to_list, we’ll need to store pointer variable p to keep track of the “current” its return value into first: node: first = add__ to list(first, 10); for (p = first; p != NULL; p = p->next) first = add_to_list(first, 20); … • Getting add__ to list to update first • A loop of this form can be used in a function that directly, rather than return a new value for searches a list for an integer n. first, turns out to be tricky.

54 Copyright © 2008 W. W. Norton & Company. 56 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Searching a Linked List Searching a Linked List • If it find s n, the f uncti on will ret urn a poi nt er t o th e • AthlttiAnother alternative: node containing n; otherwise, it will return a null struct node *search_list(struct node *list, int n) { poitinter. for (; list != NULL && list->value != n; list = list->next) • An initial version of the function: ; struct node *search_list(struct node *list, int n) return list; { } struct node *p; • Since list is NULL if we reach the end of the list, for (p = list; p != NULL; p = p->next) returning list is correct even if we don’t find n. if (p->value == n) return p; return NULL; }

57 Copyright © 2008 W. W. Norton & Company. 59 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Searching a Linked List Searching a Linked List • There are many oth er ways t o writ e searchlith_list. • This versi on of searchlith_list mihtbight be a bit • One alternative is to eliminate the p variable, instead clearer if we used a while statement: using list ilfkitself to keep track kfh of the current nod e: struct node *search_list(struct node *list, int n) { struct node *search_list(struct node *list, int n) while (list != NULL && list->value != n) { liiist = list->next; for (; list != NULL; list = list->next) return list; if (list->value == n) } return list; return NULL; } • Since list ifhiilliiis a copy of the originallist pointer, there’s no harm in changing it within the function.

58 Copyright © 2008 W. W. Norton & Company. 60 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Deleting a Node from a Linked List Deleting a Node from a Linked List • Abig a dvan tage o f s tor ing da ta in a liklinke dlitidlistis • AthtAssume that lis t hthfllihas the following appearance that we can easily delete nodes. and n is 20: • Deleting a node involves three steps: 1. Locate the node to be deleted. 2. Alter the previous node so that it “bypasses” the • After cur = list, prev = NULL has been deleted node. executed: 3. Call free to reclaim the space occupied by the deleted node. • Step 1 is harder than it looks, because step 2 requires changing the previous node. • There are vari ous sol uti ons t o thi s probl em.

61 Copyright © 2008 W. W. Norton & Company. 63 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Deleting a Node from a Linked List Deleting a Node from a Linked List • The “t raili ng poi nt er”t ” tech ni que i nvol ves k eepi ng a • The t est cur != NULL && cur->l>value !=nis pointer to the previous node (prev) as well as a true, since cur is pointing to a node and the node pointer to the current node (cur). d’tti20doesn’t contain 20. • Assume that list points to the list to be searched •After prev = cur, cur = cur->next has and n is the integer to be deleted. been executed: • A loop that implements step 1: for (cur = lis t, prev = NULL; cur != NULL && cur->value != n; pp,rev = cur, cur = cur->next) ; • When the loop terminates, cur points to the node to bdlbe deleted and prev poihidints to the previous node.

62 Copyright © 2008 W. W. Norton & Company. 64 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Deleting a Node from a Linked List Deleting a Node from a Linked List • The t est cur != NULL && cur->l>value !=nis • Step 3i 3 is t o rel ease th e memory occupi edb d by th e again true, so prev = cur, cur = cur->next current node: itdis executed once more: free(cur);

• Since cur now points to the node containing 20, the condition cur->value != n is false and the ltitloop terminates.

65 Copyright © 2008 W. W. Norton & Company. 67 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Deleting a Node from a Linked List Deleting a Node from a Linked List • NtNext, we’ll ’llf perform th thbe bypass requi idbtredby step 2 . • The dltdelete_ from_ litlist ftifunction uses th e • The statement strategy just outlined. prev->next = cur->next; • When given a list and an integer n, the function makes the pppointer in the previous node point to the deletes the first node containing n. node after the current node: • If no node contains n, delete_from_list does nothing. • In either case, the function returns a pointer to the list. • Deleting the first node in the list is a special case that requires a different bypass step.

66 Copyright © 2008 W. W. Norton & Company. 68 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Program: Maintaining a Deleting a Node from a Linked List Parts Database (Revisited) struct node *delete _ from_ list(struct node * list, int n) { •The inventory2.c program is a modification struct node *cur, *prev; of the parts database program of Chapter 16, with for (cur = list, prev = NULL; the database stored in a linked list this time. cur != NULL && cur->value != n; prev = cur, cur = cur->next) • Advantaggges of using a linked list: ; if (cur == NULL) – No need to put a limit on the size of the database. return list; /* n was not found */ if (prev == NULL) – Database can easilyyp be kept sorted b ypart number. list = list->next; /* n is in the first node */ • In the original program, the database wasn’t else prev->next = cur->next; /* n is in some other node */ sorted. free(cur); return list; }

69 Copyright © 2008 W. W. Norton & Company. 71 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Program: Maintaining a Ordered Lists Parts Database (Revisited) • When th e nod es of a li st are k epti t in ord er—sortdted •The part structure will contain an additional by the data stored inside the nodes—we say that member (a pointer to the next node): the li sti t is ordddered. struct part { • Inserting a node into an ordered list is more int number; difficult, because the node won’t always be put at ch[har name[NAME_LEN+ 1]; the beginning of the list. int on_hand; struct part *next; • However, searching is faster: we can stop looking }; after reachinggp the point at which the desired node • inventory will point to the first node in the list: would have been located. struct part *inventory = NULL;

70 Copyright © 2008 W. W. Norton & Company. 72 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Program: Maintaining a Program: Maintaining a Parts Database (Revisited) Parts Database (Revisited) • Most of the functions in the new program will • Since the list of parts is sorted, find_part can stop closely resemble their counterparts in the original when it finds a node containing a part number that’s program. greatthter than or equalt ltthdido the desired part numb er. • find_part and insert will be more complex, • find_part’s search loop: however, since we’ll keep the nodes in the for (p = inventory; p != NULL && number > p->number; inventory list sorted by part number. ppp= p->next) ; • When the loop terminates, we’ll need to test whether the part was found: if (p != NULL && number == p->number) return p;

73 Copyright © 2008 W. W. Norton & Company. 75 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Program: Maintaining a Program: Maintaining a Parts Database (Revisited) Parts Database (Revisited) • In the original program, find_part returns an • The original version of insert stores a new part index into the inventory array. in the next available array element. • In the new program, find_part will return a • The new version must determine where the new pppointer to the node that contains the desired part ppgart belongs in the list and insert it there. number. • It will also check whether the part number is • If it doesn’t find the pp,art number, find_part already present in the list. will return a null pointer. • A loop that accomplishes both tasks: for (cur= inventory, prev = NULL; cur != NULL && new_node->number > cur->number; prev = cur, cur = cur->next) ;

74 Copyright © 2008 W. W. Norton & Company. 76 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Program: Maintaining a /********************************************************** * main: Prompts the user to enter an operation code, * Parts Database (Revisited) * then calls a function to perform the requested * * action. Repeats until the user enters the * • Once the loop terminates, insert will check * command 'q'. Prints an error message if the user * whether cur isn’t NULL and whether * enters an illegal code. * **********************************************************/ new_node->number equals cur->number. int main(void) { – If both are true, the part number is already in the list. char code; –Otherwise, insert will insert a new node between the prev cur for (;;) { nodes pointed to by and . printf("Enter operation code: "); • This strategy works even if the new part number is scanf(" %c", &code); while (getchar() != '\n') /* skips to end of line */ larger than any in the list. ; • Like the original program, this version requires the read_ line function of Chapter 16.

77 Copyright © 2008 W. W. Norton & Company. 79 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers

swith(d){itch(code){ inventory2.c case 'i': insert(); /* Maintains a parts database (linked list version) */ break; case ' s' : search(); #include break; #include case 'u': update(); #include "readline.h" break; #define NAME_LEN 25 case 'p': print(); struct part { break; int number; case 'q': return 0; char name[NAME_LEN+1]; default: printf("Illegal code\n"); int on_hand; } struct part *next; printf("\n"); }; } struct part *inventory = NULL; /* points to first part */ } struct part *find_ part(int number); void insert(void); void search(void); void update(void); void print(void);

78 Copyright © 2008 W. W. Norton & Company. 80 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers

/********************************************************** for (cur = inven tory, prev = NULL; * find_part: Looks up a part number in the inventory * cur != NULL && new_node->number > cur->number; * list. Returns a pointer to the node * prev = cur, cur = cur->next) * containing the part number; if the part * ; * number is not found, returns NULL. * if (cur != NULL && new_node->number == cur->number) { **********************************************************/ printf("Part already exists.\n"); struct part * find_part(int number) free(new_ node); { return; struct part *p; } printf("Enter part name: "); for (p = inventory; read_line(new_node->name, NAME_LEN); p != NULL && number > p->number; printf("Enter quantity on hand: "); p = p->next) scanf(" %d", &new_ node->on_hand); ; if (p != NULL && number == p->number) new_node->next = cur; return p; if (prev == NULL) return NULL; inventory = new_node; } else prev->next = new_node; }

81 Copyright © 2008 W. W. Norton & Company. 83 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers

/********************************************************** /********************************************************** * insert: Prompts the user for information about a new * * search: Prompts the user to enter a part number, then * * part and then inserts the part into the * * looks up the part in the database. If the part * * inventory list; the list remains sorted by * * exists, prints the name and quantity on hand; * * part number. Prints an error message and * * if not, prints an error message. * * returns prematurely if the part already exists * **********************************************************/ * or space could not be allocated for the part. * void search(void) **********************************************************/ { void insert(void) int number; { struct pppart *p; struct part *cur, *prev, *new_node; printf("Enter part number: "); new_node = malloc(sizeof(struct part)); scanf("%d", &number); if (new_node == NULL) { p = find_part(number); printf("Database is full; can't add more parts.\n"); if (p != NULL) { return; printf("Part name: %s\n", p->name); } printf("Quantity on hand: %d\n", p->on_hand); } else printf("Enter part number: "); printf("Part not found.\n"); scanf("%d", &new_no de->b)>number); }

82 Copyright © 2008 W. W. Norton & Company. 84 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers

/********************************************************** * update: Prompts the user to enter a part number. * Pointers to Pointers * Prints an error message if the part doesn't * * exist; otherwise, prompts the user to enter * * change in quantity on hand and updates the * • Chapt er 13 int rod ucedth d the id ea of a poitinter to a * database. * pointer. **********************************************************/ void update(void) • The concept of “pointers to pointers” also pops up { int number, change; frequently in the context of linked data structures. struct part *p; • In particular, when an argument to a function is a printf("Enter part number: "); scanf("%d", &number); ppyointer variable, we may want the function to be p = find_part(number); if (p != NULL) { able to modify the variable. printf("Enter change in quantity on hand: "); scanf("%d", &c hange ); • Doing so requires the use of a pointer to a pointer. p->on_hand += change; } else printf(" Part not found.\nn);"); }

85 Copyright © 2008 W. W. Norton & Company. 87 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers

/********************************************************** * print: Prints a listing of all parts in the database, * Pointers to Pointers * showing the part number, part name, and * * quantity on hand. Part numbers will appear in * • The add_ to_ lis t ftiifunction is passed a poi itnter * ascending order. * **********************************************************/ to the first node in a list; it returns a pointer to the void print(void) { firs t nod e i n th e upd at edli d list : struct part *p; struct node *add_to_list(struct node *list, int n) pp(rintf("Part Number Part Name " { "Quantity on Hand\n"); struct node *new_node; for (p = inventory; p != NULL; p = p->next) new_node = malloc(sizeof(struct node)); printf("%7d %-25s%11d\n", p->number, p->name, if (new_node == NULL) { p->on_hand); printf("Error: malloc failed in add_to_list\n"); } exit(EXIT_FAILURE); } new_node->value = n; new_node->next = list; return new_ node; }

86 Copyright © 2008 W. W. Norton & Company. 88 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Pointers to Pointers Pointers to Pointers • MdifiModifying add_ to_ lis t so thatit t it assi gns • When th e new versi on of add_ to_ lis t is new_node to list instead of returning called, the first argument will be the address of new_node d’tkdoesn’t work. firs t: •Example: add_to_list(&first, 10); add_to_list(first, 10); • Since list is assigned the address of first, we • At the point of the call, first is copied into can use *list as an alias for first. list. • In particular, assigning new_node to *list will • If the function changes the value of list,making, making modify first. it point to the new node, first is not affected.

89 Copyright © 2008 W. W. Norton & Company. 91 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Pointers to Pointers Pointers to Functions • Ge tting add_ to_ lis t tdifto modify firs t requires • Cdoesn ’t requi re th thtat poi itnters poi itnt onl y t o dtdata; passing add_to_list a pointer to first: it’s also possible to have pointers to functions. voidddtlit(ttid add_to_list(struct no d**litit)de **list, int n) { • Functions occupy memory locations, so every struct node *new_node; function has an address. new_node = malloc(sizeof(struct node)); • We can use function pointers in much the same if (new_node == NULL) { pp(rintf("Error: malloc failed in add__ to list\n"); wayyp we use pointers to data. exit(EXIT_FAILURE); } • Passing a function pointer as an argument is fairly new_ node->value = n; common. new_node->next = *list; *list = new_node; }

90 Copyright © 2008 W. W. Norton & Company. 92 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Function Pointers as Arguments The qsort Function • Afunc tion named itintegra te thati t int egrat es a • Some o ffth the mos t usef ulf l functi ons i n th e C library mathematical function f can be made as general as require a function pointer as an argument. possible by passing f as an argument. • One of these is qsort, which belongs to the • Prototype for integrate : header. double integrate(double (*f)(double), • qsort is a general-purpose sorting function that’s double a, double b); cappgyyable of sorting any array. The parenth eses around *f iditindicate th thtat f is a pointer to a function. • An alternative prototype: double integrate(double f(double), double a, double b);

93 Copyright © 2008 W. W. Norton & Company. 95 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Function Pointers as Arguments The qsort Function • AllfA call of itintegra te thati t int egrat es th e sin • qsort mustbe t old ldh how t o d et ermi ne whi hihch of (sine) function from 0 to /2: two array elements is “smaller.” result = integrate(sin, 0.0, PI / 2); • This is done by passing qsort a pointer to a • When a function name isn’t followed by comparison function. parentheses, the C compiler produces a pointer to • When given two pointers p and q to array the function. elements, the comparison function must return an • Within the body of integrate, we can call the integer that is: function that f points to: – Negative if *p is “less than” *q y = (*f)(x); – Zero if *p is “equal to” *q • Writing f(x) instead of (* f)(x) is allowed. – Positive if *p is “greater than” *q

94 Copyright © 2008 W. W. Norton & Company. 96 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers The qsort Function The qsort Function • PttPrototype f or qsort: • Writi ng th e compare_parts ftiitikfunction is tricky. void qsort(void *base, size_t nmemb, size_t size, • qsort requires that its parameters have type int (* compar)(const void * , const void * )); void *, but we can’t access the members of a • base must point to the first element in the array part structure through a void * pointer. (or the first element in the portion to be sorted). • To solve the problem, compare_parts will • nmemb is the number of elements to be sorted. assign its parameters, p and q, to variables of type • size ihis the si ze of each array el ement, measured struct part *. in bytes. • compar is a pointer to the comparison function.

97 Copyright © 2008 W. W. Norton & Company. 99 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers The qsort Function The qsort Function • When qsort illdittthitis called, it sorts the array into • AifA version of compare_parts that can b e used ascending order, calling the comparison function to sort the inventory array into ascending order whitdthenever it needs to compare array el ltements. btbby part number: • A call of qsort that sorts the inventory array int compare_parts(const void *p, const void *q) { of Chapter 16: const struct part *p1 = p; qsort(inventory, num_parts, const struct part *q1 = q; sizeof(struct part), compare_parts); if (p1->number < q1->number) • compare_parts is a function that compares return -1; else if (p1->number == q1->number) two part structures. return 0; else return 1; }

98 Copyright © 2008 W. W. Norton & Company. 100 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers The qsort Function The qsort Function • MtCMostC programmers wou lditthfld write the functi on • AifA version of compare_parts that can b e used more concisely: to sort the inventory array by part name iiiint compare_parts(const void *p, const void *q) itdfinstead of part numb er: { if (((struct part *) p)->number < int compare_parts(const void *p, const void *q) ((struct part *) q)->number) { return strcmp(((struct part *) p)->name, return -1; ((struct part *) q)->name); else if (((struct part *) p)->number == } ((struct part *) q)->number) return 0; else return 1; }

101 Copyright © 2008 W. W. Norton & Company. 103 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers The qsort Function Other Uses of Function Pointers • compare_parts can bdbe made even sh htborter by • Althoughf h functi on poi nt ers are oft en used as removing the if statements: arguments, that’s not all they’re good for. int compare_parts(const void *p, const void *q) • C treats pointers to functions just like pointers to { return ((struct pppart *) p)->number - data. ((struct part *) q)->number; • They can be stored in variables or used as } elements of an array or as members of a structure or union. • It’ s even possible for functions to return function pointers.

102 Copyright © 2008 W. W. Norton & Company. 104 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Other Uses of Function Pointers Other Uses of Function Pointers • A var ia ble that can st ore a poi nt er t o a f uncti on • A ca ll ofth f the f uncti on st oredi d in positi on n ofthe with an int parameter and a return type of void: file_cmd array: void (*pf)(int); (*file_cmd[n])(); /* or file_cmd[n](); */ • If f is such a function, we can make pf point to f • We could get a similar effect with a switch in the following way: statement, but using an array of function pointers pf = f; provides more flexibility. • We can now call f by writing either (* pf)(i); or pf(i);

105 Copyright © 2008 W. W. Norton & Company. 107 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers

Other Uses of Function Pointers Program: Tabulating the Trigonometric Functions • AhltftiitAn array whose elements are function pointers: • The tblttabulate.c program pritints t tblables sh owi ng void (*file_cmd[])(void) = {new_cmd, the values of the cos, sin, and tan functions. open_cmd, • The program is built around a function named close_cmd, tabulate close__ all cmd, that, when passed a function pointer save_cmd, f, prints a table showing the values of f. save_as_cmd, • tabulate uses the ceil function. save_all_cmd, print_cmd, • When given an argument x of double type, exit_ cmd ceil returns the smallest integgger that’s greater }; than or equal to x.

106 Copyright © 2008 W. W. Norton & Company. 108 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers

Program: Tabulating the Trigonometric Functions tabulate.c /* Tabulates values of trigonometric functions */ • A sess ion w ith tblttabulate.c: #include Enter initial value: 0 #include Enter final value: .5 Enter increment: .1 void tabulate(double (*f)(double), double first, double last, double incr); x cos(x) ------int main(v oid) 0.00000 1.00000 { 0.10000 0.99500 double final, increment, initial; 0. 20000 0.98007 printf("Enter initial value: "); 0.30000 0.95534 scanf("%lf", &initial); 0.40000 0.92106 0.50000 0.87758 printf(" Enter final value: " ); scanf("%lf", &final);

printf("Enter increment: "); scanf("%lf", &increment);

109 Copyright © 2008 W. W. Norton & Company. 111 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers printf("\n x cos(x)" "\n ------\n"); Program: Tabulating the Trigonometric Functions tabulate(cos, initial, final, increment); x sin(x) printf("\n x sin(x)" ------"\n ------\n"); 0.00000 0.00000 tabulate(sin, initial, final, increment); 0.10000 0.09983 pp(rintf("\n x tan(()x)" 0.20000 0.19867 "\n ------\n"); 0.30000 0.29552 tabulate(tan, initial, final, increment); return 0; 0.40000 0.38942 } 0.50000 0.47943 void tabulate(double (*f)(double), double first, x tan(x) double last, double incr) ------{ 0.00000 0.00000 double x; int i, num_intervals; 0.10000 0.10033 0. 20000 0.20271 num_intervals = ceil((last - first) / incr); for (i = 0; i <= num_intervals; i++) { 0.30000 0.30934 x = first + i * incr; 0.40000 0.42279 printf("%10.5f %10.5f\n", x, (*f)(x)); } 0. 50000 0.54630 }

110 Copyright © 2008 W. W. Norton & Company. 112 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Restricted Pointers (C99) Restricted Pointers (C99) • IC99thkIn C99, the keyword restittrict may appear in • To ill ust rat e th e use of restittrict, consider th e the declaration of a pointer: memcpy and memmove functions. int * restrict p; • The C99 prototype for memcpy, which copies p is said to be a restricted pointer. bytes from one object (pointed to by s2) to • The intent is that if p points to an object that is another (pointed to by s1): later modified,,j then that object is not accessed in void *memcpy(void * restrict s1, any way other than through p. const void * restrict s2, size_t n); • Having more than one way to access an object is • The use of restrict with both s1 and s2 often called aliasing. indicates that the objects to which they point shld’houldn’t overl ap.

113 Copyright © 2008 W. W. Norton & Company. 115 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Restricted Pointers (C99) Restricted Pointers (C99) • CidthflliConsider the following cod e: • IttIn contrast, restittrict d’tithdoesn’t appear in the int * restrict p; prototype for memmove: it*int* res tittrict q; void *memmove(void *s1, const void *s2, p = malloc(sizeof(int)); size_t n); • Normally it would be legal to copy p into q and • memmove iiilis similar to memcpy, bibut is guaranteed then modify the integer through q: to work even if the source and destination overlap. q = p; • Example of using memmove to shift the elements *q = 0; /* causes undefined behavior */ of an array: • Because p ititditthfftfis a restricted pointer, the effect of int a[100]; executing the statement *q=0;is undefined. … memmove(&a[0], &a[1], 99 * sizeof(int));

114 Copyright © 2008 W. W. Norton & Company. 116 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Restricted Pointers (C99) Flexible Array Members (C99) • PiPrior to C99 C99th, there was no way t o d ocumentth e • Occas ionally ll, we’ll needt d to d efi ne a st ruct ure th at difference between memcpy and memmove. contains an array of an unknown size. • The prototypes for the two functions were nearly • For examplihle, we might want a structure th at stores identical: the characters in a string together with the string’s void *memcpy(void *s1, const void *s2, lthlength: size_t n); struct vstring { void*id *memmove (vo id*1id *s1, const vo id*2id *s2, itlintlen; size_t n); char chars[N]; • The use of restittrict ithC99in the C99 versi on of }; memcpy’s prototype is a warning that the s1 and • Using a fixed-length array is undesirable: it limits s2 objec ts sh ould not overl ap. the length of the string and wastes memory.

117 Copyright © 2008 W. W. Norton & Company. 119 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Restricted Pointers (C99) Flexible Array Members (C99) • restittrict provides i nf ormati on t o th e compil er • C programmers traditi ona lly sol ve thi s probl em b y that may enable it to produce more efficient declaring the length of chars to be 1 and then code—a process known as optimi zati on. dynami call y a lloca ting each st ri ng: • The C99 standard guarantees that restrict has struct vstring { no effect on the behavior of a program that itlintlen; char chars[1]; conforms to the standard. }; • Most programmers won’t use restrict unless … they’re fine-tuninggpg a program to achieve the best struct vstring *str = malloc(siz eof(stru ct v str ing) + n - 1); possible performance. str->len = n; • This technique is known as the“ struct hack.”

118 Copyright © 2008 W. W. Norton & Company. 120 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Flexible Array Members (C99) Flexible Array Members (C99) • The st ructh t hacki k is support edb d by many compil ers. • Spec illftial rules for struct ures th thttifliblat contain a flexible • Some (including GCC) even allow the chars array member: array to have zero length. – The flexible array must be the last member. • The C89 standard doesn’t guarantee that the struct – The structure must have at least one other member. hack will work, but a C99 feature known as the • Copying a structure that contains a flexible array ffylexible array member serves the same pppurpose. member will copy the other members but not the flexible array itself.

121 Copyright © 2008 W. W. Norton & Company. 123 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 17: Advanced Uses of Pointers Chapter 17: Advanced Uses of Pointers Flexible Array Members (C99) Flexible Array Members (C99) • When the l ast memb er of a st ruct ure i s an array, it s • A s truc ture th thtat cont tiains a fl fliblexible array memb er i s length may be omitted: an incomplete type. struct vstring { int len; •An ilincomplete type i iiifhs missing part of the char chars[]; /* flexible array member - C99 only */ information needed to determine how much memory }; it requi res. • The length of the array isn’t determined until memory • Incomplete types are subject to various restrictions. is allocated for a vstring structure: struct vstring *str = • In particular, an incomplete type can’t be a member malloc(sizeof(struct vstring) + n); of another structure or an element of an array. str->len = n; • However, an array may contain pointers to sizeof ignores the chars member when computing structures that have a flexible array member. thesizeofthestructurethe size of the structure.

122 Copyright © 2008 W. W. Norton & Company. 124 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Declaration Syntax • Dec larati on specifi ers f all int o th ree cat egori es: – Storage classes Chapter 18 – Type qualifiers – Type specifiers • C99 has a fourth category, function specifiers, Declarations which are used only in function declarations. – This category has one member, the keyword inline. •Type qualifiers and typ e s pecifiers should follow the storage class, but there are no other restrictions on their order.

1 Copyright © 2008 W. W. Norton & Company. 3 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Declaration Syntax Declaration Syntax • Dec lara tions f urni shi h inf ormati on t o th e compil er ab out • There are f our sttlorage classes: auto, sttitatic, the meaning of identifiers. extern, and register. • ElExamples: • At most one storage class may appear in a int i; declaration; if present, it should come first. float f(float); • In C89, there are only two type qualifiers: const • General form of a declaration: and volatile. declaration-specifiers declarators ; restrict • Declaration specifiers describe the properties of the • C99 has a third type qualifier, . variables or functions being declared. • A declaration may contain zero or more type • Declarators give their names and may provide qualifiers. additional information about their properties.

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Declaration Syntax Declaration Syntax • The k eyword s void, char, shthort, itint, long, • AdltiithtAdeclaration with a storage cl ass andth dthdltree declarators: float, double, signed, and unsigned are all type specifiers. • The order in which they are combined doesn’t matter. – itint unsidigned long is the same as long unsidigned int. • A declaration with a type qualifier and initializer but no • Type specifiers also include specifications of stltorage class: structures, unions, and enumerations. – Examples: struct point { int x, y; }, struct { int x, y; }, struct point. •typedef names are also type sp ecifiers.

5 Copyright © 2008 W. W. Norton & Company. 7 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Declaration Syntax Declaration Syntax • DlDeclarat ors i ildnclude: • AAd dec larati on with a st orage cl ass, a t ype qualifi er, and – Identifiers (names of simple variables) three type specifiers: – Identifiers followed by [] (array names) – Identifiers preceded by * (pointer names) – Identifiers followed by () (function names)

• Declarators are separated by commas. • Function declarations may have a storage class, type • A declarator that represents a variable may be qualifiers, and type specifiers: followed by an initializer.

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Storage Classes Properties of Variables • Storage cl asses can b e specifi edf d for vari abl es • The sttdtiorage duration ofibldtif a variable determines and—to a lesser extent—functions and when memory is set aside for the variable and parameters. whththen that memory i s rel eased . • Recall that the term block refers to the body of a – Automatic storage duration: Memory for variable is function (the part in braces) or a compound allocat ed wh en th e surroundi ng bl ocki k is execut ed and statement, possibly containing declarations. deallocated when the block terminates. – Static storage duration: Variable stays at the same storage location as long as the program is running, allowinggy it to retain its value indefinitely.

9 Copyright © 2008 W. W. Norton & Company. 11 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Properties of Variables Properties of Variables • EibliChthEvery variable in a C program has three • The scope ofiblithtifthf a variable is the portion ofthe properties: program text in which the variable can be – Storage duration refdferenced. – Scope – Block scope: Variable is visible from its point of – Linkage dldeclarati titthdfthon to the end ofthe encl liosing bl blkock. – File scope: Variable is visible from its point of declaration to the end of the enclosing file.

10 Copyright © 2008 W. W. Norton & Company. 12 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Properties of Variables Properties of Variables • The link age ofibldtithtttf a variable determines the extentto • ElExample: which it can be shared. – External linkage: Variable may be shared by several (perhaps all) files in a program. – ItInterna llikllinkage: Var ibliiable is rest titdtrictedto a si ngl e fil e but may be shared by the functions in that file. – No linkage: Variable belongs to a single function and can’t be shared at all. • We can alter these properties by specifying an explicit storage class: auto, static, extern, or register.

13 Copyright © 2008 W. W. Norton & Company. 15 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Properties of Variables The auto Storage Class • The d ef ault st orage d urati on, scope, andli d link age of • The auto stlilllfibltorage class is legal only for variables a variable depend on where it’s declared: that belong to a block. – Variables declared inside a block (including a function •An auto variable has automatic storage duration, body) have automatic storage duration, block scope, block scope, and no linkage. and no linkage. •The auto storage class is almost never specified – Variables declared outside any block, at the outermost level of a program, have static storage duration, file exppylicitly. scope, and external linkage.

14 Copyright © 2008 W. W. Norton & Company. 16 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations The static Storage Class The static Storage Class • The sttitatic storage cl ass can b e used with all • When use d ou ts ide a bl ock , sttitatic hides a vari abl e variables, regardless of where they’re declared. within a file: – When used outside a block , static specifies th at a static int i; /* no access to i in other files */ variable has internal linkage. void f1(void) { – When used iidinside a block , sttitatic chthhanges the /* has access to i */ variable’s storage duration from automatic to static. } void f2(vo id) { /* has access to i */ } • This use of static is helpful for implementing information hiding.

17 Copyright © 2008 W. W. Norton & Company. 19 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations The static Storage Class The static Storage Class • ElExample: • A sttitatic variabl e d ecl ared withi n a bl ock resides at the same storage location throughout program execution. •A static variable retains its value indefinitely. • Properties of static variables: – A static variable is initialized onlyyp once, prior to program execution. –A static variable declared inside a function is shared by all calls of the function, including recursive calls. – A function may return a pointer to a static variable.

18 Copyright © 2008 W. W. Norton & Company. 20 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations The static Storage Class The extern Storage Class • DliDeclaring a l ocal vari ibltbable to be sttitatic allows a • There’ s one excepti on t o th e rul e th at an extern function to retain information between calls. declaration of a variable isn’t a definition. • Mft’llMore often, we’ll use sttitatic fffor reasons of •An extern declaration that initializes a variable efficiency: serves as a definition of the variable. char diitthdigit_to_hex_ch ar(i (itdiit)ntdigit) { • For example, the declaration static const char hex_chars[16] = extern int i = 0; "0123456789ABCDEF"; is effectively the same as return hex_chars[digit]; } int i = 0; • Declaring hex_chars to be static saves time, • This rule prevents multiple extern declarations because sttitatic variables are initialized only once . from initializing a variable in different ways.

21 Copyright © 2008 W. W. Norton & Company. 23 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations The extern Storage Class The extern Storage Class • The extern stlblltorage class enables several source • AibliA variable in an extern dldeclarati tilon always h as files to share the same variable. static storage duration. • A variable declaration that uses extern doesn’t • If the declaration is inside a block, the variable has cause memory to be allocated for the variable: block scope; otherwise, it has file scope: extern int i; In C terminology, this is not a definition of i. •An extern declaration tells the compiler that we need access to a variable that’s defined elsewhere. • A variable can have many declarations in a program but should have only one definition.

22 Copyright © 2008 W. W. Norton & Company. 24 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations The extern Storage Class The register Storage Class • De term ini ng th e li nk age of an extern varibliiable is • The regitister stlilllftorage class is legal only for a bit harder. variables declared in a block. – If th e vari abl e was d ecl ared static earlier i n th e fil e •A register variable has the same storage (outside of any function definition), then it has internal duration, scope, and linkage as an auto variable. linkage. • Since registers don’t have addresses, it’s illegal to – Otherwise (the normal case), the variable has external linkage. use the & operator to take the address of a register variable. • This restriction applies even if the compiler has elected to store the variable in memory.

25 Copyright © 2008 W. W. Norton & Company. 27 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations The register Storage Class The register Storage Class • UiUsing th e regitister stlithtorage class in the • regitister ibis best usedf or vari iblthtables that are declaration of a variable asks the compiler to store accessed and/or updated frequently. the vari abl e i n a regi st er. • The loop control variable in a for statement is a •A register is a high-speed storage area located in a good candidate for register treatment: computer’s CPU. int sum_array(int a[], int n) { •Sppygecifying the storag e class of a variable to be register int i; register is a request, not a command. int sum = 0;

•The compiler is free to store a register for (i = 0; i < n; i++) variable in memory if it chooses. sum += a[i]; return sum; }

26 Copyright © 2008 W. W. Norton & Company. 28 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations The register Storage Class The Storage Class of a Function • regitister i’tisn’t as popul ar as it once was. • ElExamples: • Many of today’s compilers can determine extern int f(int i); automatically which variables would benefit from sttiittatic int g (iti)(inti); being kept in registers. int h(int i); • Using extern is unnecessary, but sttitatic has • Still, using register provides useful benefits: information that can helpppp the compiler optimize the performance of a program. – EiEasier mai ntenance. A static ftii’tiiblfunction isn’t visible outside the file in which its definition appears, so future • In particular, the compiler knows that a modifications to the function won’t affect other files. register variable can’t have its address taken, – Reduced “name space pollution.” Names of static and therefore can’t be modified through a pointer. functions don’t conflict with names used in other files.

29 Copyright © 2008 W. W. Norton & Company. 31 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations The Storage Class of a Function The Storage Class of a Function • Ftidlti(ddfiiti)Function declarations (anddefinitions) may • FtiFunction paramet thers have th e same properti es as include a storage class. auto variables: automatic storage duration, block • The only options are extern and static: scope, andlikd no linkage. – extern specifies that the function has external • The only storage class that can be specified for linkage, allowing it to be called from other files. parameters is register. – static indicates internal linkage, limiting use of the functi on’ s name to th e fil e i n whi chi h it’ s d efi ned . • If no storage class is specified, the function is assumed to have external linkage.

30 Copyright © 2008 W. W. Norton & Company. 32 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Summary Summary • AftththllibltA program fragmentthat shows all possible ways to • Of the four s torage cl asses, th e mosti t import ant are include—or omit—storage classes in declarations of static and extern. variables and parameters: • auto has no effect, and modern compilers have int a; extern int b; made register less important. static int c; void f(int d, register int e) { auto int g; int h; static int i; extern int j; register int k; }

33 Copyright © 2008 W. W. Norton & Company. 35 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Summary Type Qualifiers Name Storage Duration Scope Linkage • There are t wo t ype qualifi ers: const and a static file external b static file † volatile. c static file internal – C99 has a t hir d type qua lifier, restrict, whichi h is d automatic block none used only with pointers. e automatic block none •volillatile idiis discussedi diChtn Chapter 20 . g automatic block none h automatic block none • const is used to declare “read-only” objects. i static block none •Examples: j static block † k automatic block none const int n = 10; const int tax_brackets[] = †In most cases, b and j will be defined in another file and will {750, 2250, 3750, 5250, 7000}; have external linkage.

34 Copyright © 2008 W. W. Norton & Company. 36 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Type Qualifiers Type Qualifiers • Advan tages ofd f decl ari ng an obj ectt t to b e const: • The val ue of a const objec t, un like th e val ue of a – Serves as a form of documentation. macro, can be viewed in a debugger. – Allows the compiler to check that the value of the • Unlike macros, const objects can’t be used in object isn’t changed. constant expressions: – Aler ts the compil er th atth t the obj ect can b e st oredi d in const int n = 10; ROM (read-only memory). int a[n]; /*** WRONG ***/ • It’s legal to apply the address operator (&) to a const object, since it has an address; a macro doesn’t have an address.

37 Copyright © 2008 W. W. Norton & Company. 39 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Type Qualifiers Type Qualifiers • It mi ght appear th at const serves the same rol e • There are no ab sol ltute rul es th thtdittatdictate wh en t o as the #define directive, but there are use #define and when to use const. siifitdiffignificant differences b btetween th thte two f fteatures. • #define is good for constants that represent • #define can be used to create a name for a numbers or characters. numerical, character, or string constant, but const can create read-only objects of any type. • const objects are subject to the same scope rules as variables; constants created using #define aren’t.

38 Copyright © 2008 W. W. Norton & Company. 40 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Declarators Declarators • IthiIn the simpl ltest case, a d ecl arat or i ijts just an • C99 provid es t wo additi onal opti ons f or wh at goes identifier: between the brackets in the declaration of an array int i; parameter: • Declarators may also contain the symbols *, [], – The keyword static, followed by an expression that and (). specifies th e array’ s mi ni mum l ength . – The * symbol, which can be used in a function • A declarator that begins with * represents a prototype to indicate a variable-length array argument. pointer: • Chapter 9 discusses both features. int *p;

41 Copyright © 2008 W. W. Norton & Company. 43 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Declarators Declarators • AAd dec larat or th at end s with [] represents an array: • AAd dec larat or th at end s with () represents a int a[10]; function: • The brackets may be left empty if the array is a int abs(int i); parameter, if it has an initializer, or if its storage void swap(int *a, int *b); class is extern: int find_ largest(int a[], int n); extern int a[]; • C allows parameter names to be omitted in a ftidltifunction declaration: • In the case of a multidimensional array, only the int abs(int); first set of brackets can be emppyty. void swap (it*(int*, it*)int*); int find_largest(int [], int);

42 Copyright © 2008 W. W. Norton & Company. 44 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Declarators Deciphering Complex Declarations • The parenth eses can even b e l eft empt y: • Bu t wh at ab outd t decl arat ors lik e th e one i n th e int abs(); following declaration? void swap() ; int *(*x[10])(void); int find_largest(); • It’s not obvious whether x is a pointer, an array, or This provid es no i nf ormati on ab outth t the argument s. a function. • Putting the word void between the parentheses is different: it indicates that there are no arguments. • The empty-parentheses style doesn’t let the compiler check whether function calls have the right arguments.

45 Copyright © 2008 W. W. Norton & Company. 47 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Declarators Deciphering Complex Declarations • DlDeclarat ors i n act tlual programs oft en combi bithne the • RlRules f or und erst andi ng d ecl arati ons: *, [], and () notations. – Always read declarators from the inside out. Locate • An array of 10 pointers to integers: the id entifi er th at’ s b ei ng d ecl ared , and st art deciphering the declaration from there. int *ap[10]; – When there’s a choice, always favor [] and () over • A function that has a float argument and returns *. Parentheses can be used to override the normal a pointer to a float: ppyriority of [] and () over *. float *fp(float); • A pointer to a function with an int argument and a void return type: void (* pf)(int);

46 Copyright © 2008 W. W. Norton & Company. 48 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Deciphering Complex Declarations Deciphering Complex Declarations • El1Example 1: • UdUnders tan ding a compl d ecl arat or oft en int *ap[10]; involves zigzagging from one side of the identifier ap is an array of pointers. tththto the other: •Example 2: float *fp(float); fp is a function that returns a pointer.

49 Copyright © 2008 W. W. Norton & Company. 51 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Deciphering Complex Declarations Deciphering Complex Declarations • El3Example 3: • AdA second examp lf“ii”le of“zigzagging”: void (*pf)(int); • Since *pf is enclosed in parentheses, pf must be a pointer. •But (*pf) is followed by (int), so pf must point to a function with an int argument. •The word void represents the return type of this function.

50 Copyright © 2008 W. W. Norton & Company. 52 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Deciphering Complex Declarations Initializers • CtithiCertain things can’t ’tbd be decl aredi diCn C. • For conven ience, C all ows us t o specif y i niti al • Functions can’t return arrays: values for variables as we’re declaring them. int f(int)[]; /*** WRONG ***/ • To initialize a variable, we write the = symbol • Functions can’t return functions: after its declarator, then follow that with an int g(int)(int); /*** WRONG ***/ initializer. • Arrays of functions aren’t possible, either: int a[10](int); /*** WRONG ***/ • In each case, pointers can be used to get the desired effect. • For example, a function can’t return an array, but it can return a pointer to an array.

53 Copyright © 2008 W. W. Norton & Company. 55 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations

Using Type Definitions to Simplify Declarations Initializers • StdfiitithlSome programmers use type definitions to help • The i niti ali zer f or a si mpl e vari abl e i s an simplify complex declarations. expression of the same type as the variable: • Suppose that x is declared as follows: int i = 5 / 2; /* i is initially 2 */ int *(*x[10])(void); • If the types don’t match, C converts the initializer • The following type definitions make x’s type using the same rules as for assignment: easier to understand: int j = 5.5; /* converted to 5 */ typedef int *Fcn(void); • The initializer for a pointer variable must be an typedef Fcn *Fcn_ptr; exppypypression of the same type or of type void *: typedef Fcn_ptr Fcn_ptr_array[10]; int *p = &i; Fcn_ptr_array x;

54 Copyright © 2008 W. W. Norton & Company. 56 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Initializers Initializers • The i niti a lizer f or an array, st ruct ure, or uni on i s • If a var iabl e h as aut omati c st orage d urati on, it s usually a series of values enclosed in braces: initializer need not be constant: int a[5] = {1, 2, 3, 4, 5}; int f(int n) • In C99, brace-enclosed initializers can have other { int last = n - 1; forms, thanks to designated initializers. … }

57 Copyright © 2008 W. W. Norton & Company. 59 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Initializers Initializers • An in itia lizer f or a vari abl e with st ati c st orage • Abrace-enclosedi d initi a lizer f or an array, st ruct ure, duration must be constant: or union must contain only constant expressions: #define FIRST 1 #define N 2 #define LAST 100 int powers[5] = static int i = LAST - FIRST + 1; {1,N,N*N,N*N*N,N*N*N*N}; • If LAST and FIRST had been variables, the • If N were a variable, the initializer would be initializer would be illegal. illegal. • In C99, this restriction applies only if the variable has static storage duration.

58 Copyright © 2008 W. W. Norton & Company. 60 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Initializers Inline Functions (C99) • The i niti a lizer for an au toma tic st ruct ure or uni on • C99 functi on d ecl arati ons may cont ai n th e can be another structure or union: keyword inline. void g(struct part part1) • inline is related to the concept of the { “overhead” of a function call—the work required struct part part2 = part1; to call a function and later return from it. … } • Although the overhead of a function call slows the • The initializer doesn’t have to be a variable or program by only a tiny amount, it may add up in parameter name, although it does need to be an certain situations. expression of the proper type.

61 Copyright © 2008 W. W. Norton & Company. 63 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Uninitialized Variables Inline Functions (C99) • The i niti al val ue of a vari abl e d epend s on it s • In C89, the onl y way t o avoid the overh ead of a storage duration: function call is to use a parameterized macro. – Variables with automatic storage duration have no • C99 offers a better solution to this problem: create default initial value. an inline function. – Var iabl es w ith sttitatic storage d dtihthluration have the value • The word “inline” suggests that the compiler zero by default. reppylaces each call of the function by the machine • A s tati c var iabl e i s correctl y i niti a lizedb d based on instructions for the function. its type, not simply set to zero bits. • This technique may cause a minor increase in the • It’s better to provide initializers for static variables size of the compiled program. rather than rely on the fact that they’re guaranteed to be zero.

62 Copyright © 2008 W. W. Norton & Company. 64 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Inline Functions (C99) Inline Definitions (C99) • DliDeclaring a f uncti titbon to be iliinline d’tdoesn’t • There are t wo ways t o avoid this error. actually force the compiler to “inline” the • One option is to add the word static to the ftifunction. function definition: • It suggests that the compiler should try to make static inline double average(double a, double b) { calls of the function as fast as possible, but the return (a + b) / 2; compiler is free to ignore the suggestion. } • average now has internal linkage, so it can’t be called from other files. • Other files may contain their own definitions of average, which might be the same or different.

65 Copyright © 2008 W. W. Norton & Company. 67 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Inline Definitions (C99) Inline Definitions (C99) • An inli ne f uncti on h as th e k eyword iliinline as one of • The oth er opti on i s t o provid e an ext ernal its declaration specifiers: definition for average so that calls are permitted in line dou ble average(d oubl e a, dou ble b) fthfilfrom other files. { return (a + b) / 2; • One way to do this is to write the average } function a second time (without using inline) • average has external linkage, so other source files and put this definition in a different source file. may contain calls of average. • However, it’s not a good idea to have two versions average • However, the definition of isn’t an external of a function: we can’t ggyuarantee that they’ll defi niti on (it’ s an inli ne d efi niti on itd)instead). remain consistent when the program is modified. • Attempting to call average from another file will be considered an error.

66 Copyright © 2008 W. W. Norton & Company. 68 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Inline Definitions (C99) Inline Definitions (C99) • AAb be tter approac hhi is t o putth t the i nli ne d efi niti on of • AllIflltA general rule: If all top-lldltifleveldeclarations of a average in a header file: function in a file include inline but not #ifndef AVERAGE_H extern, then the de fin ition ofth f the f uncti on i n th at #define AVERAGE_H file is inline. inline double average(double a, double b) • If the function is used anywhere in the program, { an external definition of the function will need to return (a + b) / 2; } be provided by some other file. #endif • Let’s name this file average.h.

69 Copyright © 2008 W. W. Norton & Company. 71 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Inline Definitions (C99) Inline Definitions (C99) • NtNext, we’ll ’llt create a mat thiching source fil e, • When an i nli ne f uncti on i s call ed , th e compil er h as average.c: a choice: #include "average.h" – Perform an ordinary call (using the function’s external definition). extern double average(double a, double b); – Per form iliinline expansi on ( usi ng th thfe functi ti’on’s i ilinline • Any file that needs to call the average function definition). can include average.h. • Because the ch oi ce i s l eft to th e compil er, it’ s • The definition of average included from crucial that the two definitions be consistent. average. h will be treated as an external • The technique just discussed (using the definition in average.c. average.h and average.c files) guarantees that the definitions are the same.

70 Copyright © 2008 W. W. Norton & Company. 72 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 18: Declarations Chapter 18: Declarations Restrictions on Inline Functions (C99) Using Inline Functions with GCC (C99) • Res tri cti ons on i nli ne f uncti ons with ext ernal • FtithtFunctions that are specifi ifidtbbthedto be both sttitatic linkage: and inline should work fine, regardless of the – May not de fine a modifi abl e static varibliable. versifGCCion of GCC. – May not contain references to variables with internal • This strategy is legal in C99 as well, so it’s the link age. safest bet. • Such a function is allowed to define a variable that •A static inline function can be used within ibis both static and const. a single file or placed in a header file and included • However, each inline definition of the function into any source file that needs to call the function. may create its own copy of the variable.

73 Copyright © 2008 W. W. Norton & Company. 75 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 18: Declarations Chapter 18: Declarations Using Inline Functions with GCC (C99) Using Inline Functions with GCC (C99) • Some comp ilers, i ncl ldiuding GCC , support tdiliedinline • Atech n ique f or sh ari ng an i nli ne f uncti on among functions prior to the C99 standard. multiple files that works with older versions of • Their rules for using inline functions may vary GCC but confli ct s with C99: from the standard. – Put a definition of the function in a header file. • The scheme described earlier (using the – Specify th at th e f uncti on i s b oth extern and inline. average.h and average.c files) may not – Include the header file into any source file that contains work with these compilers. a call ofth f the f uncti on. – Put a second copy of the definition—without the words • Version 4.3 of GCC is expected to support inline extern and inline—in one of the source files. functions in the way described in the C99 • A final note about GCC: Functions are “inlined” standard. onlhthly when the -O command-line opti on i s used .

74 Copyright © 2008 W. W. Norton & Company. 76 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Introduction • Issues th at ari se wh en writi ng a l arge program: – Style Chapter 19 – Documentation – Maintenance – Design Program Design • This chapter focuses on design techniques that can make C programs readable and maintainable.

1 Copyright © 2008 W. W. Norton & Company. 3 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Introduction Modules • MtfllMostfull-fea tured programs are atl t least 100,000 • It’s oft en usef ult l to ew a program as a numb er of lines long. independent modules. • Although C wasn’t designed for writing large • A module is a collection of services, some of programs, many large programs have been written which are made available to other parts of the in C. program (the clients). • Writingggpg large programs is quite different from • Each module has an interface that describes the writing small ones. available services. • The details of the module—including the source code for the services themselves—are stored in the module’s implementation.

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Modules • IthIn the cont ext tfC“ ofC, “servi ces” are f uncti ons. • The interface of a module is a header file containing prototypes for the functions that will be made available to clients (source files). • The implementation of a module is a source file that contains definitions of the module’s functions.

5 Copyright © 2008 W. W. Norton & Company. 7 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Modules Modules • The ca lcul at or program sk et ch edi d in Ch apt er 15 • The C library i s it self a coll ecti on of mod ul es. consists of: • Each header in the library serves as the interface – calc.c, which contai ns th e main fifunction to a module. – A stack module, stored in stack.h and stack.c – is the interface to a module containing • calc.c is a client of the stack module. I/O functions. • stack.h is the interface of the stack module. – is the interface to a module containing string-hdlifhandling functi ons. • stack.c is the implementation of the module.

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Modules Modules • Advant ages ofdi f dividi ng a program i nt o mod ul es: • Reusabilit y. AdlthtidiiAny module that provides services is – Abstraction potentially reusable in other programs. – Reusability • Since it’s often hard to anticipate the future uses – Maintainability of a module, it’s a good idea to design modules for reusability.

9 Copyright © 2008 W. W. Norton & Company. 11 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Modules Modules • Abst racti on. AldiddlbA properly designed module can be • MitiMaintainabilit y. A sma ll bug will usuall y aff ect treated as an abstraction; we know what it does, only a single module implementation, making the btbut we d on’t worry ab outh ow it work s. bitltdfibug easier to locate andfix. • Thanks to abstraction, it’s not necessary to • Rebuilding the program requires only a understand how the entire program works in order recompilation of the module implementation to make changes to one part of it. (followed by linking the entire program). • Abstraction also makes it easier for several • An entire module implementation can be replaced members of a team to work on the same ppgrogram. if necessary.

10 Copyright © 2008 W. W. Norton & Company. 12 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Modules Cohesion and Coupling • Ma in tai nabilit y i s th e most criti cal ad vant age. • IllIn a well-didesigned program, mod dlules sh ould ldh have • Most real-world programs are in service over a two properties. period of years • High cohesion. The elements of each module •Duringgp this period, bu gs are discovered, should be closely related to one another. enhancements are made, and modifications are – High cohesion makes modules easier to use and makes made to meet changgging req uirements. the entire program easier to understand. • Designing a program in a modular fashion makes • Low coupling. Modules should be as independent maintenance much easier. of each other as possible. – Low coupling makes it easier to modify the program and reuse modules.

13 Copyright © 2008 W. W. Norton & Company. 15 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Modules Types of Modules • DiiDecisions t tbo be mad ddie during mod dldiular design: • MdlModules t endt dtfllito fall into cert tiain cat egori es: – What modules should a program have? – Data pools – What services should each module provide? – Libraries – How should the modules be interrelated? – Abstract objects – Abstract data types

14 Copyright © 2008 W. W. Norton & Company. 16 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Types of Modules Information Hiding • A dtdata pool is a coll lltiection of rel ltdated vari iblables • AllA well-didesigned mod dlftkule often keeps some and/or constants. information secret from its clients. – In C, a module of this type is often just a header file. – Clients of the stack module have no need to know – and are both data pools. whether the stack is stored in an array, in a linked list, or in some other form. •A library is a collection of related functions. – is the interface to a library of string- • Deliberately concealing information from the handling functions. clients of a module is knownas n as ifinformati on hiding.

17 Copyright © 2008 W. W. Norton & Company. 19 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Types of Modules Information Hiding • An abtbstract obj ect illtifftithtis a collection offunctions that • PiPrimary a dvant ages ofi nf ormati on hidi ng: operate on a hidden data structure. – Security. If clients don’t know how a module stores its •An abstract data type (ADT) is a type whose da ta, th ey won’t be abl e t o corruptitb t it by t amperi ng with representation is hidden. its internal workings. – Flexibility. Making changes—no matter how large—to – Client modules can use the type to declare variables but a module’s internals won’t be difficult. have no knowledge of the structure of those variables. – To perform an operation on such a variable, a client must call a function provided by the ADT.

18 Copyright © 2008 W. W. Norton & Company. 20 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Information Hiding stack.h #ifndef STACK_H • In C, th e maj or t oolf l for enf orci ng i nf ormati on #define STACK_H hiding is the static storage class. #include /* C99 only */ – A static varibliable wi ihfilth file scope h as i nternal void make_empty(void); linkage, preventing it from being accessed from other bool is_empty(void); files, including clients of the module. bool is_ full(void); void push(int i); –A static function can be directly called only by int pop(void); other functions in the same file. #endif

21 Copyright © 2008 W. W. Norton & Company. 23 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design A Stack Module stack1.c #include • To see th e b enefit s ofi f inf ormati on hidi ng, l et’ s #include look at two implementations of a stack module, #include "stack.h" one using an array andth d the oth er a li nk edli d list . #define STACK_ SIZE 100 • stack.h is the module’s header file. static int contents[STACK_SIZE]; static int topp; = 0; • stack1.c uses an array to implement the stack. static void terminate(const char *message) { prin tf("%s\n")", message); exit(EXIT_FAILURE); }

void make_empty(void) { top = 0; }

22 Copyright © 2008 W. W. Norton & Company. 24 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design bliboolis_emp t(id)ty(void) { A Stack Module return top == 0; } • The st acki k impl ement ati on red one usi ng PUBLIC and bool is_full(void) { PRIVATE: return top == STACK_ SIZE; } PRIVATE int contents[STACK_ SIZE]; PRIVATE int top = 0; void push(int i) { PRIVATE void terminate(const char *message) { … } if (is_full()) terminate("Error in push: stack is full."); PUBLIC void make_empty(void) { … } contents[top++] = i; } PUBLIC bool is_empty(void) { … } int pop(void) { PUBLIC bool is_full(void) { … } if (is_empty()) terminate("Error in pop: stack is empty."); PUBLIC void push(int i) { … } return contents[--top]; } PUBLIC int pop(void) { … }

25 Copyright © 2008 W. W. Norton & Company. 27 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design A Stack Module A Stack Module • MbdtidiththftiMacros can be usedto indicate whether a function •stk2tack2.c ilikdis a linked-listi t impl ement ati on ofth f the or variable is “public” (accessible elsewhere in the stack module. program) or “pri vat e” (limit edt d to a si ngl e fil e) : #define PUBLIC /* empty */ #de fine PRIVATE s ta tic •The word static has more than one use in C; PRIVATE makitltht’kes it clear that we’re usi ng it itt to enforce information hiding.

26 Copyright © 2008 W. W. Norton & Company. 28 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design

itint pop (vo id) stack2.c { #include struct node *old_top; #inc lu de int i; #include "stack.h" if (is_empty()) struct node { terminate(" Error in pop: stack is empty." ); int data; struct node *next; }; old_top = top; i = top->data; static struct node *top = NULL; top = top->next; static void terminate(const char *message) free(old_top); { return i; printf("%s\n", message); } exit(EXIT_FAILURE); } void make_empty(void) { while (!is_empty()) pop(); }

29 Copyright © 2008 W. W. Norton & Company. 31 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design bliboolis_emp t(id)ty(void) { A Stack Module return top == NULL; } • Thank s t o i nf ormati on hidi ng, it doesn’t matt er bool is_full(void) whether we use stack1.c or stack2.c to { return false; ilimplementth tthtkdle stack module. } • Both versions match the module’s interface, so we void push(int i) can switch from one to the other without having to { struct node *new_node = malloc(sizeof(struct node)); make changes elsewhere in the program. if (new_node == NULL) terminate("Error in push: stack is full.");

new_node->data = i; new_node->next = top; top = new_node; }

30 Copyright © 2008 W. W. Norton & Company. 32 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Abstract Data Types Abstract Data Types • AdlthtA module that serves as an ab bttbjthstract objecthas a • CtithConverting the stkhtack.h hdheader so th thtitatit serious disadvantage: there’s no way to have provides a Stack type requires adding a Stack multipl e i nst ances ofth f the obj ect . (or Stac k *)tthfti) parameter to eachfunction. • To accomplish this, we’ll need to create a new type. • For example, a Stack type can be used to create any number of stacks.

33 Copyright © 2008 W. W. Norton & Company. 35 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Abstract Data Types Abstract Data Types • AftthtttkA program fragmentthat uses two stacks: • Changes to stkhtack.h are shihown in bldbold: Stack s1, s2; #define STACK_SIZE 100 make_empty(&s1); typedef struct { make_empty(&s2); int contents[STACK_SIZE]; push(&s1, 1); int top; push(&s2, 2); if (!is_empty(&s1)) } Stack; printf("%d\n", pop(&s1)); /* prints "1" */ void make_empty(Stack *s); • To clients, s1 and s2 are abstractions that bool is_empty(const Stack *s); respond to certain operations (make_empty, bool is_full(const Stack *s); is_empty, is_full, push, and pop). void push(Stack *s, int i); int pop(Stack *s);

34 Copyright © 2008 W. W. Norton & Company. 36 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Abstract Data Types Encapsulation • The st ack paramet ers t o maktke_empty, push, • Worse still , we can’t ch ange th e way st ack s are and pop need to be pointers, since these functions stored without having to assess the effect of the modify the st ack . chlithange on clients. • The parameter to is_empty and is_full • What we need is a way to prevent clients from doesn’t need to be a pointer. knowing how the Stack type is represented. • Passing these functions a Stack pointer instead • C has onlyypp limited support for encappgsulating of a Stack value is done for efficiency, since the types in this way. latter would result in a structure beinggp copied. • Newer C-based languages, including C++ , Java, and C#, are better equipped for this purpose.

37 Copyright © 2008 W. W. Norton & Company. 39 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Encapsulation Incomplete Types • UfUnfor tuna tltely, Stac k i’tisn’t an abtbstract dtdata t ype, • The on ly too llth thatC t C gi ves us f or encapsul ati on i s since stack.h reveals what the Stack type the incomplete type. really i s. • Incomplete types are “types that describe objects • Nothing prevents clients from using a Stack but lack information needed to determine their variable as a structure: sizes.” Stack s1; •Example: s1.top = 0; struct t; /* incomplete declaration of t */ s1.contents[[p]top++] = 1; • The intent is that an incomplete type will be • Providing access to the top and contents completed elsewhere in the program. members allows clients to corrupt the stack.

38 Copyright © 2008 W. W. Norton & Company. 40 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Incomplete Types Defining the Interface for the Stack ADT • AiAn incompl lttete type can’t ’tb be usedt dtdo decl are a •stac kADT. h defi nes th e st ack ADT type and variable: gives prototypes for the functions that represent struct t s; /*** WRONG ***/ stktack operati ons. • However, it’s legal to define a pointer type that •The Stack type will be a pointer to a references an incomplete type: stack_type structure (an incomplete type). typedef struct t *T; • The members of this structure will depend on how • We can now declare variables of type T, pass them the stack is implemented. as argg,puments to functions, and perform other operations that are legal for pointers.

41 Copyright © 2008 W. W. Norton & Company. 43 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design stackADT.h A Stack Abstract Data Type (version 1) • The f oll owi ng st ack ADT will illust rat e h ow #ifndef STACKADT_ H #define STACKADT_H abstract data types can be encapsulated using ilttincomplete types. #include /> /* C99 only* / • The stack will be implemented in three different typedef struct stack_type *Stack; ways. Stack create(void); void destroy(Stack s); void make_ emppyty(Stack s); bool is_empty(Stack s); bool is_full(Stack s); void push(Stack s, int i); int pop(Stack s);

#endif

42 Copyright © 2008 W. W. Norton & Company. 44 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Defining the Interface for the Stack ADT Defining the Interface for the Stack ADT • Client s th ati t incl ud e stkADThtackADT.h will be abl e t o •stklittackclient.c can bdtttthtkbe usedto testthe stack declare variables of type Stack, each of which is ADT. capable of poi nti ng t o a stkttack_type stttructure. • It creates two stacks and performs a variety of • Clients can then call the functions declared in operations on them. stackADT.h to perform operations on stack variables. • However, clients can’t access the members of the stack_type structure, since that structure will be defined in a separate file.

45 Copyright © 2008 W. W. Norton & Company. 47 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Defining the Interface for the Stack ADT stackclient.c #include • AdlA module genera lld’tdlly doesn’t need create and #include "stackADT.h"

destroy functions, but an ADT does. int main(void) – create dilllldynamically allocates memory f or a stack kd and { Stack s1, s2; initializes the stack to its “empty” state. int n; – dtdestroy relthtk’dilllltdleases the stack’s dynamically allocated s1 = create(); memory. s2 = create();

push(s1, 1); push(s1, 2);

n = pop(s1); printf("Popped %d from s1\n", n); push(s2, n);

46 Copyright © 2008 W. W. Norton & Company. 48 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design n = pop(1)(s1); Implementing the Stack ADT printf("Popped %d from s1\n", n); push(s2, n); Using a Fixed-Length Array

destroy(s1); • There are several ways to implement the stack ADT. while (!is_empty(s2)) printf("Popped %d from s2\n", pop(s2)); • The simplest is to have the stack_type

push( (,)s2, 3); structure contain a fixed-lenggyth array: make_empty(s2); struct stack_type { if (is_empty(s2)) printf("s2 is empty\n"); int contents[STACK_SIZE]; else int top; printf("s2 is not empty\n"); }; destroy(s2);

return 0; }

49 Copyright © 2008 W. W. Norton & Company. 51 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Defining the Interface for the Stack ADT stackADT.c #include • Ou tputifth t if the st ack ADT is i mpl ement ed correctl y: #include #include "stackADT.h" Popped 2 from s1 Poppe d1from s 1 #defi ne STACK _ SIZE 100

Popped 1 from s2 struct stack_type { Popped 2 from s2 int contents[STACK_ SIZE]; s2 is empty int top; };

static void terminate(const char *message) { printf("%s\n", message); exit(EXIT_FAILURE); }

50 Copyright © 2008 W. W. Norton & Company. 52 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design

Stack creat e( void) { Changing the Item Type in the Stack ADT Stack s = malloc(sizeof(struct stack_type)); if (s == NULL) terminate("Error in create: stack could not be created."); •stac kADT.c requithttkitbires that stackitems be s->top = 0; return s; integers, which is too restrictive. } • To make the stack ADT easier to modify for void destroy(Stack s) { different item types, let’s add a type definition to free(s); } the stackADT.h header. void make_ emppyty(Stack s) • It will define a type named Item, representing the { s->top = 0; type of data to be stored on the stack. } bool is_empty(Stack s) { return s->top == 0; }

53 Copyright © 2008 W. W. Norton & Company. 55 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design boo lli is_ fu ll(Stac k s ) { stackADT.h return s->top == STACK_SIZE; (version 2) } #ifndef STACKADT_ H #define STACKADT_H void push(Stack s, int i) { #include /* C99 only* / if (is_full(s)) terminate("Error in push: stack is full."); typedef int Item; s->contents[s->topp]++] = i; tdftypedef stttruct stkttack_type *Stac k; } Stack create(void); int pop(Stack s) void destroy(Stack s); { void make_empty(Stack s); if (is_empty(s)) bool is_empty(Stack s); terminate("Error in pop: stack is empty."); bool is_ full(();Stack s); return s->contents[--s->top]; void push(Stack s, Item i); } Item pop(Stack s);

#endif

54 Copyright © 2008 W. W. Norton & Company. 56 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Implementing the Stack ADT Changing the Item Type in the Stack ADT Using a Dynamic Array • The stac kADT.c file w ill needt d to b e modifi ed , • Another problem with the stack ADT: each stack but the changes are minimal. has a fixed maximum size. • The updated stack_type structure: • There’s no way to have stacks with different struct stack_type { capppgacities or to set the stack size as the program is Item contents[STACK_SIZE]; running. int top; }; • Possible solutions to this problem: • The second parameter of push will now have – Implement the stack as a linked list. type Item. – Store stack items in a dynamically allocated array. • pop now returns a value of type Item.

57 Copyright © 2008 W. W. Norton & Company. 59 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Implementing the Stack ADT Changing the Item Type in the Stack ADT Using a Dynamic Array • The stklittackclient.c file can be use ddt to t estth t the • The latter approach involves modifying the new stackADT.h and stackADT.c to verify stack_type structure. thatth t the Stac k type still work s. •The contents member becomes a pointer to the • The item type can be changed by modifying the array in which the items are stored: definition of Item in stackADT.h. struct stack_type { Item *contents; int top; int size; }; •The size member stores the stack’s maximum size.

58 Copyright © 2008 W. W. Norton & Company. 60 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Implementing the Stack ADT stackADT2.c Using a Dynamic Array #include •The create function will now have a parameter #include #include "stackADT2.h" that specifies the desired maximum stack size: stttkt{truct stack_type { Stack create(int size); Item *contents; create int top; • When is called, it will create a int size; stack_type structure plus an array of length };

size. static void terminate(const char * message) { •The contents member of the structure will printf("%s\n", message); point to this array. exit(EXIT_ FAILURE); }

61 Copyright © 2008 W. W. Norton & Company. 63 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Implementing the Stack ADT Stac k crea te (itint s ize) { Using a Dynamic Array Stack s = malloc(sizeof(struct stack_type)); if (s == NULL) • stackADT.h will be the same as before, except terminate("Error in create: stack could not be created."); that create will have a size parameter. s->contents = malloc(size * sizeof(Item)); if (s->contents == NULL) { • The new version will be named stackADT2.h. free(s); terminate("Error in create: stack could not be created."); • stackADT.c will need more extensive } s->top = 0; modification, yielding stackADT2.c. s->size = size; return s; }

void destroy(Stack s) { free(s->contents); free(s); }

62 Copyright © 2008 W. W. Norton & Company. 64 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design void mak e_empt y(St ac k s ) Implementing the Stack ADT { s->top = 0; Using a Dynamic Array } •The stackclient.c file can again be used to bool is_empty(Stack s) test the stack ADT. { return s->top == 0; • The calls of create will need to be changed, } since create now requires an argument. bool is_full(Stack s) { •Example: return s->top == s->size; s1 = create(100); } s2 = create(200);

65 Copyright © 2008 W. W. Norton & Company. 67 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design void pus h(Stac k s, Item i) Implementing the Stack ADT { if (is_full(s)) Using a Linked List terminate("Error in push: stack is full."); s->contents[s->top++] = i; • Implementing the stack ADT using a dynamically } allocated array provides more flexibility than Item pop(Stack s) using a fixed-size array. { if (is_ emppy())ty(s)) • However, the client is still reqqpyuired to specify a terminate("Error in pop: stack is empty."); maximum size for a stack at the time it’s created. return s->contents[--s->top]; } • With a linked-list implementation, there won’ ttbe be any preset limit on the size of a stack.

66 Copyright © 2008 W. W. Norton & Company. 68 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Implementing the Stack ADT Implementing the Stack ADT Using a Linked List Using a Linked List • The linked list will consist of nodes, represented • Implementing the stack ADT using a linked list by the following structure: involves modifying the stackADT.c file to struct node { create a new version named stackADT3.c. Item data; •The stackADT.h header is unchanged. struct nod*de *next; }; • The original stackclient.c file can be used • The stkttack_type struct ure will cont ai n a poi nt er for testing. to the first node in the list: struct stack_type { struct node *top; };

69 Copyright © 2008 W. W. Norton & Company. 71 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Implementing the Stack ADT stackADT3.c Using a Linked List #include •The stack_type structure seems superfluous, #include #include "stackADT.h" since Stack could be defined to be struct sttd{truct node { node *. Item data; • However, stack_type is needed so that the struct node *next; }; interface to the stack remains unchanged. struct stack_type { • Moreover,,g having the stack_ type structure struct node * top; will make it easier to change the implementation }; in the future. static void terminate(const char *message) { printf("%s\n", message); exit(EXIT_FAILURE); }

70 Copyright © 2008 W. W. Norton & Company. 72 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design

Stack creat e( void) Item pop (Stac k s ) { { Stack s = malloc(sizeof(struct stack_type)); struct node *old_top; if (s == NULL) Item i; terminate("Error in create: stack could not be created."); s->top = NULL; if (is_empty(s)) return s; terminate(" Error in pop: stack is empty." ); } old_top = s->top; void destroy(Stack s ) i = old_ top->data; { s->top = old_top->next; make_empty(s); free(old_top); free(s); return i; } } void make_empty(Stack s) { while (!is_empty(s)) pop(s); }

73 Copyright © 2008 W. W. Norton & Company. 75 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design boo lli is_emp ty (Stac k s ) { Design Issues for Abstract Data Types return s->top == NULL; } • The st ack ADT suff ers f rom several probl ems th at bool is_full(Stack s) prevent it from being industrial-strength. { return false; } void push(Stack s, Item i) { struct node *new_node = malloc(sizeof(struct node)); if (new_node == NULL) terminate("Error in push: stack is full.");

new_node->data = i; new_node->next = s->top; s->top = new_node; }

74 Copyright © 2008 W. W. Norton & Company. 76 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 19: Program Design Naming Conventions Error Handling • The st ack ADT functi ons currentl y h ave sh ort , • The C st and ard library cont ai ns a paramet eri zed easy-to-understand names, such as create. macro named assert that can terminate a • If a program has more than one ADT, name program if a spec ifie d con dition isn ’t sa tisfi ed . clashes are likely. • We could use calls of this macro as replacements • It will probably be necessary for function names to for the if statements and calls of terminate incorporate the ADT name (stack_create). that currently appear in the stack ADT.

77 Copyright © 2008 W. W. Norton & Company. 79 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 19: Program Design Error Handling Generic ADTs • The st ack ADT deal s with errors b y di spl ayi ng an • Other probl ems w ith the s tack ADT: error message and terminating the program. – Changing the type of items stored in a stack requires • It might be better to provide a way for a program modifying the definition of the Item tpetype. to recover from errors rather than terminating. – A program can’t create two stacks whose items have different types. • An alternative is to have the push and pop functions return a bool value to indicate whether • We’d like to have a single “generic” stack type. or not they succeeded. • There’s no completely satisfactory way to create such a type in C.

78 Copyright © 2008 W. W. Norton & Company. 80 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 19: Program Design Chapter 20: Low-Level Programming Generic ADTs • The most common approach uses void * as the item type: void push(Stack s, void *p); void *pop(Stack s); Chapter 20 pop returns a null poi nter if th e stacki k is empty. • Disadvantages of using void * as the item type: Low-Level Programming – Doesn’t work for data that can’t be represented in pointer form, including basic types such as int and double. – Error checking is no longer possible, because stack items can b e a mi xt ure of poi nt ers of differentt t types.

81 Copyright © 2008 W. W. Norton & Company. 1 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 19: Program Design Chapter 20: Low-Level Programming ADTs in Newer Languages Introduction • These probl ems are d ealt with much more cl eanl y • PiPrevious c hthhapters have d escrib ibdC’hihedC’s high-lllevel, in newer C-based languages. machine-independent features. – Name clashes are prevented by defining function names • However, some kinds of programs need to within a class. perform operations at the bit level: – Excepti on h andli ng allows f uncti ons t o “th row” an – Systems programs (including compilers and operating exception when they detect an error condition. systems) – Some languages provide special features for defining – Encryption programs generic ADTs. (C++ templates are an example.) – Graphics programs – Programs for which fast execution and/or efficient use of space is critical

82 Copyright © 2008 W. W. Norton & Company. 2 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Bitwise Operators Bitwise Shift Operators • CidiC provides six bitwi se operat ors, which operat e on • The val ue of i << j ithis the resu lthlt when thbitithe bits in integer data at the bit level. i are shifted left by j places. • Two of these operators perform shift operations. – For eac hhbi bit t hat is “shif ted off” th e l ef t end of i, a zero bit enters at the right. • The other four ppperform bitwise complement, bitwise and, bitwise exclusive or, and bitwise • The val ue of i >> j ithis the result lth when i ihiftdis shifted inclusive or operations. right by j places. – If i is of an unsigned type or if the value of i is nonnegative, zeros are added at the left as needed. – If i itithltiilttiis negative, the result is implementation-dfiddefined.

3 Copyright © 2008 W. W. Norton & Company. 5 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Bitwise Shift Operators Bitwise Shift Operators • The bit wi se shift operat ors shift the bit s i n an • Exampl lillttithfftflithes illustrating the effect of applying the integer to the left or right: shift operators to the number 13: << lef t shif t unsigned short i, j; >> right shift i = 13; • The operands for << and >> may be of any integer /* i isnow13 (binary 0000000000001101) */ type (including char). j = i << 2; /* j is now 52 (binary 0000000000110100) */ • The integer promotions are performed on both j = i >> 2; opp;erands; the result has the typ e of the left /* j is now 3 ((ybinary 0000000000000011) */ operand after promotion.

4 Copyright © 2008 W. W. Norton & Company. 6 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Bitwise Complement, And, Bitwise Shift Operators Exclusive Or, and Inclusive Or • To modif y a vari abl e b y shifti ng it s bit s, use th e • There are four additional bitwise operators: compound assignment operators <<= and >>=: ~ bitwise complement i = 13; & bitwise and /* i is now 13 (binary 0000000000001101) */ ^ bitwise exclusive or i<<2;i<<= 2; /* i is now 52 (binary 0000000000110100) */ | bitwise inclusive or i>>i>>2;= 2; •The ~ oppy;gperator is unary; the integer promotions /* i is now 13 (binary 0000000000001101) */ are performed on its operand. • The other operators are binary; the usual arithmetic conversions are performed on their operands.

7 Copyright © 2008 W. W. Norton & Company. 9 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Bitwise Complement, And, Bitwise Shift Operators Exclusive Or, and Inclusive Or • The bit wi se shift operat ors h ave l ower preced ence •The ~, &, ^, and | operators perform Boolean than the arithmetic operators, which can cause operations on all bits in their operands. surprises: •The ^ operator produces 0 whenever both i<<2+1means i<<(2+1), not (i << 2) + 1 operands have a 1 bit, whereas | produces 1.

8 Copyright © 2008 W. W. Norton & Company. 10 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Bitwise Complement, And, Bitwise Complement, And, Exclusive Or, and Inclusive Or Exclusive Or, and Inclusive Or • Examples of the ~, &, ^, and | operators: • Each of the ~, &, ^, and | operators has a different unsigned short i, j, k; precedence: i = 21; Highest: ~ /* i is now 21 (binary 0000000000010101) */ j = 56; & /* j is now 56 (binary 0000000000111000) */ ^ k = ~i; /* k is now 65514 (binary 1111111111101010) * / Lowest: | k = i & j; •Examples: /* k is now 16 (binary 0000000000010000) */ i&~j | k means (i&(~ j)) | k k = i ^ j; /* k is now 45 (binary 0000000000101101) */ i^j&~k means i ^ (j & (~k)) k = i | j; • Using parentheses helps avoid confusion. /* k is now 61 (binary 0000000000111101) */

11 Copyright © 2008 W. W. Norton & Company. 13 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Bitwise Complement, And, Bitwise Complement, And, Exclusive Or, and Inclusive Or Exclusive Or, and Inclusive Or •The ~ operator can be used to help make low-level • The compound assignment operators &=, ^=, and programs more portable. |= correspond to the bitwise operators &, ^, and |: – An integer whose bits are all 1: ~0 i = 21; /* i is now 21 (binary 0000000000010101) */ – An integer whose bits are all 1 except for the last five: ~0x1f j56j = 56; /* j is now 56 (binary 0000000000111000) */ i&= j; /* i is now 16 (binary 0000000000010000) */ i ^= j; /* i is now 40 (binary 0000000000101000) */ i |= j; /* i isnow56 (binary 0000000000111000 )*/

12 Copyright © 2008 W. W. Norton & Company. 14 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Using the Bitwise Operators to Access Bits Using the Bitwise Operators to Access Bits • The bit w ise opera tors can b e usedt d to ext ract or • Cleari ng a bit . Cleari ng bit 4 of i requikires a mask modify data stored in a small number of bits. with a 0 bit in position 4 and 1 bits everywhere • Common single-bit operations: else: – Setting a bit i = 0x00ff; /* i is now 0000000011111111 */ – Clearing a bit – Testing a bit i &= ~0x0010; /* i is now 0000000011101111 */ • Assumptions: –iis a 16-bit unsigned short variable. • A statement that clears a bit whose position is storedin a vari abl e: – The leftmost—or most significant—bit is numbered 15 and the least significant is numbered 0. i &= ~(1 << j); /* clears bit j */

15 Copyright © 2008 W. W. Norton & Company. 17 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Using the Bitwise Operators to Access Bits Using the Bitwise Operators to Access Bits • Se tting a bit . The easi est way t o set bit 4 of i itis to • TtiTesting a bit . An if stttatementth tthttattest s wh hthether or the value of i with the constant 0x0010: bit 4 of i is set: i = 0x0000; if (i & 0x0010) … /* tests bit 4 */ /* i is now 0000000000000000 */ • A statement that tests whether bit j is set: i|= 000100x0010; if (i & 1 << j) … /* tests bit j */ /* i is now 0000000000010000 */ • If the position of the bit is stored in the variable j, a shift operator can be used to create the mask: i|= 1<

16 Copyright © 2008 W. W. Norton & Company. 18 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Using the Bitwise Operators to Access Bits Using the Bitwise Operators to Access Bits • Worki ng with bits i s easi er if they are gi ven • It’s al so easy t o set , cl ear, or t est several bits at names. time: • Suppose that bits 0, 1, and 2 of a number i |= BLUE | GREEN; correspond to the colors blue, green, and red, /* sets BLUE and GREEN bits */ respectively. i &= ~(BLUE | GREEN); /* clears BLUE and GREEN bits */ • Names that repppresent the three bit positions: if (i & (BLUE | GREEN)) … #define BLUE 1 /* tests BLUE and GREEN bits */ #define GREEN 2 #define RED 4 • The if statement tests whhhether e ihither th e BLUE bit or the GREEN bit is set.

19 Copyright © 2008 W. W. Norton & Company. 21 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming

Using the Bitwise Operators to Access Bits Using the Bitwise Operators to Access Bit-Fields • Exampl es of setti ng, cl eari ng, andt d testi ng th e • Dea ling with a group of several consecuti ve bit s ( a BLUE bit: bit-field) is slightly more complicated than i |= BLUE; /* sets BLUE bit */ working w ith si ngl e bit s. i &= ~BLUE; /* clears BLUE bit */ • Common bit-field operations: if (i & BLUE) … /* tests BLUE bit */ – Modifying a bit-field – Retrieving a bit-field

20 Copyright © 2008 W. W. Norton & Company. 22 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming

Using the Bitwise Operators to Access Bit-Fields Using the Bitwise Operators to Access Bit-Fields • Mo difyi ng a bit -fie ld. Mo difyi ng a bit -fie ld • RtiRetrievi ng a bit -fie ld. FthiFetching a bit -fie ld atth t the requires two operations: right end of a number (in the least significant bits) – A bitwise and (to clear the bit-field) is easy: – A bitwise or (to store new bits in the bit-field) j = i & 0x0007; •Example: /* ret ri eves bit s 0-2*/ i = i & ~0x0070 | 0x0050; • If the bit-field isn’t at the right end of i, we can /* stores 101 in bits 4-6 */ first shif t th e bi t-fie ld to th e endb d bef ore extracti ng •The & operator clears bits 4–6 of i; the | operator the field using the & operator: then sets bits 6 and 4. j = (i >> 4) & 0x0007; /* retrieves bits 4-6 */

23 Copyright © 2008 W. W. Norton & Company. 25 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming

Using the Bitwise Operators to Access Bit-Fields Program: XOR Encryption • TlithlTo generalize the example, assume th thtat j contitains • OfthilttOne ofthe simplest ways to encryptd tdtitata is to the value to be stored in bits 4–6 of i. exclusive-or (XOR) each character with a secret •jwill need to be shifted into position before the key. bitwise or is performed: • Suppose that the key is the & character. i = (i & ~0x0070) | (j << 4); • XORing this key with the character z yields the \ /* stores j in bits 4-6 */ character: •The | operator has lower precedence than & and 00100110 (ASCII code for &) <<, so the parentheses can be dropped: XOR 01111010 (ASCII code for z) i = i & ~0x0070 | j << 4; 01011100 (ASCII code for \)

24 Copyright © 2008 W. W. Norton & Company. 26 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Program: XOR Encryption Program: XOR Encryption • DtiDecrypting a message i idbliths done by applying the • AlfildA sample file named msg: same algorithm: Trust not him with your secrets, , when left 00100110 (ASCII co de for &) alone in your room, turns over your papers. --Johann Kaspar Lavater (1741-1801) XOR 01011100 (ASCII code for \) 01111010 (ASCII code for z) • A command that encrypts msg,savingthe, saving the encrypted message in newmsg: xor newmsg • Contents of newmsg: rTSUR HIR NOK QORN _ IST UCETCRU, QNI, QNCH JC@R GJIHC OH _IST TIIK, RSTHU IPCT _IST VGVCTU. --lINGHH mGUVGT jGPGRCT (1741-1801)

27 Copyright © 2008 W. W. Norton & Company. 29 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Program: XOR Encryption Program: XOR Encryption • The xor.c program encryptbts a message by • AdthtthiilA commandthat recovers the original message XORing each character with the & character. and displays it on the screen: • The original message can be entered by the user or xor

28 Copyright © 2008 W. W. Norton & Company. 30 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Program: XOR Encryption Bit-Fields in Structures • The xor.c program won’t ch ange some • The bit -fie ld tec hn iques discusse d prev ious ly can characters, including digits. be tricky to use and potentially confusing. • XORing these characters with & would produce • Fortunately, C provides an alternative: declaring invisible control characters, which could cause structures whose members represent bit-fields. problems with some operating systems. •The ppgrogram checks whether both the orig inal character and the new (encrypted) character are ppgrinting characters. • If not, the program will write the original character instead of the new character.

31 Copyright © 2008 W. W. Norton & Company. 33 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming xor.c Bit-Fields in Structures /* Performs XOR encryption */ #include • Exampl e: H ow DOS st ores th e d at e at whi ch a fil e #include was created or last modified. #de fine KEY '&' • Since days, months, and years are small numbers, int main(void) { storing them as normal integers would waste int orig_char, new_char; space. while ((orig_char = getchar()) != EOF) { new_ char = orig_char ^ KEY; • Instead, DOS allocates only 16 bits for a date, if (isprint(orig_char) && isprint(new_char)) putchar(new_char); with 5 bits for the day, 4 bits for the month, and 7 else bits for the year: putch(ihar(orig_ch h)ar); } return 0; }

32 Copyright © 2008 W. W. Norton & Company. 34 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Bit-Fields in Structures Bit-Fields in Structures • AAC C s truct ure th at uses bit -fie lds to crea te an • AbitA bit-fie ld can b e usedi d in th e same way as any identical layout: other member of a structure: struct file_date { struct file_date fd; unsigned int day: 5; unsigned int month: 4; fd.day = 28; unsigned int year: 7; fd.month = 12; }; fd.year = 8; /* represents 1988 */ • A condensed version: • Appearance of the fd variable after these struct file_ date { assignments: unsigned int day: 5, month: 4, year: 7; };

35 Copyright © 2008 W. W. Norton & Company. 37 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Bit-Fields in Structures Bit-Fields in Structures • The t ype of a bit -fie ld mustb t be eith er itint, • The add ress operat or ( &)’tblidtbit) can’t be appliedto a bit- unsigned int, or signed int. field. • Using int is ambiguous; some compilers treat the • Because of this rule, functions such as scanf field’s high-order bit as a sign bit, but others can’t store data directly in a bit-field: don’t. scanf("%d", &fd.day); /*** WRONG ***/ • In C99, bit-fields may also have type _Bool. • We can still use scanf to read input into an • C99 compilers may allow additional bit-field ordinary variable and then assign it to fd.day. types.

36 Copyright © 2008 W. W. Norton & Company. 38 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming How Bit-Fields Are Stored How Bit-Fields Are Stored • The C st and ard all ows th e compil er consid erabl e • AtiithAssumptions in the file_ da te example: latitude in choosing how it stores bit-fields. – Storage units are 16 bits long. • The rules for handling bit-fields depend on the – Bit-fields are allocated from right to left (the first bit- notion of “storage units.” field occupies the low-order bits). • The size of a storage unit is implementation- • A8An 8-bit storage uni t i s al so acceptabl e if th e defined. compiler splits the month field across two storage – Typical values are 8 bits, 16 bits, and 32 bits. units.

39 Copyright © 2008 W. W. Norton & Company. 41 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming How Bit-Fields Are Stored How Bit-Fields Are Stored • The compil er pack s bit -fie lds one b y one i nt o a • The name of a bit -fie ld can be omitt ed . storage unit, with no gaps between the fields, until • Unnamed bit-fields are useful as “padding” to there’ s not enough room f or th e nextfi t field . ensure that other bit-fields are properly positioned. • At that point, some compilers skip to the • A structure that stores the time associated with a beginning of the next storage unit, while others DOS file: split the bit-field across the storage units. struct file_ time { • The order in which bit-fields are allocated (left to unsigned int seconds: 5; riggght or right to left ) is also im plementation- unsigned int minutes: 6; defined. unsigned int hours: 5; };

40 Copyright © 2008 W. W. Norton & Company. 42 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming How Bit-Fields Are Stored Other Low-Level Techniques • The same st ruct ure with the name ofth f the • SftSome features covere diihtdin previous chapters are seconds field omitted: used often in low-level programming. struct file_time { •Examples: unsigned int : 5; /* not used */ – Defining types that represent units of storage unsigned int minutes: 6; unsigned int hours: 5; – Using unions to bypass normal type-checking }; – Using pointers as addresses • The remaining bit-fields will be aligned as if •The volatile type qualifier was mentioned in seconds were still present. Chapter 18 but not discussed because of its low- level nature.

43 Copyright © 2008 W. W. Norton & Company. 45 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming How Bit-Fields Are Stored Defining Machine-Dependent Types • The length of an unnamed bit-field can b e 0 : • The char tibthttype occupies one byte, so characters struct s { can be treated as bytes. unsigg;ned int a: 4; unsigned int : 0; /* 0-length bit-field */ • It’s a good idea to define a BYTE type: unsigned int b: 8; typedef unsigned char BYTE; }; • A 0-length bit-field tells the compiler to align the • Depending on the machine, additional types may following bit-field at the beginning of a storage unit. be needed. – If storage units are 8 bits long, the compiler will allocate 4 bits • A useful type for the x86 platform: for a, skip 4 bits to the next storage unit, and then allocate 8 bits for b. typedef unsigned short WORD; – If storage units are 16 bits long, the compiler will allocate 4 bits for a, skip 12 bits, and then allocate 8 bits for b.

44 Copyright © 2008 W. W. Norton & Company. 46 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming

Using Unions to Provide Multiple Views of Data Using Unions to Provide Multiple Views of Data • UiUnions can b e use din a port tblable way, as sh own i n • AAf func tion th at pri nt s an unsidigned shthort Chapter 16. argument as a file date: • However, they’re often used in C for an entirely void print_date(unsigned short n) different purpose: viewing a block of memory in { two or more different ways. union int_date u; • Consider the file_date structure described u.i = n; earlier. printf("%d///%d/%d\n", u.fd.month, u.fd.day, u.fd.year + 1980); •A file_ date structure fits into two byy,tes, so } any two-byte value can be thought of as a file_ date structure.

47 Copyright © 2008 W. W. Norton & Company. 49 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming

Using Unions to Provide Multiple Views of Data Using Unions to Provide Multiple Views of Data • ItilIn particular, an unsidigned shthort valblue can be • Us ing un ions t o all ow multi pl e vi ews ofd f dat a i s viewed as a file_date structure. especially useful when working with registers, • A union that can be used to convert a short integer whihhich are oft en di diidditvidedinto small er unit s. to a file date or vice versa: • x86 processors have 16-bit registers named AX, union int_date { BX, CX, and DX. unsigned short i; • Each register can be treated as two 8-bit registers. struct file_ date fd; – AX is divided into registers named AH and AL. };

48 Copyright © 2008 W. W. Norton & Company. 50 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming

Using Unions to Provide Multiple Views of Data Using Unions to Provide Multiple Views of Data • Writi ng l ow-lllevel appli litifcations for x86 -bdbased • The memb ers ofth f the word struct ure will be computers may require variables that represent overlaid with the members of the byte structure. AX, BX, CX, an ddDX DX. –axwill occupy th e same memory as al and ah. • The goal is to access both the 16- and 8-bit • An example showing how the regs union might registers, taking their relationships into account. be used: – A change to AX affects both AH and AL; changing AH regs.byte.ah = 0x12; or AL modifies AX. regs.byte.al = 0x34; • The solution is to set up two structures: printf("AX: %hx\n", regs.word.ax); – The members of one correspond to the 16-bit registers. • Output: – The members of the other match the 8-bit registers. AX: 1234

51 Copyright © 2008 W. W. Norton & Company. 53 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming

Using Unions to Provide Multiple Views of Data Using Unions to Provide Multiple Views of Data • A un ion th at encl oses th e t wo st ruct ures: • NtNote thtththatthe btbyte stttructure li litsts al bfbefore ah. union { • When a data item consists of more than one byte, stt{truct{ there are two logical ways to store it in memory: WORD ax, bx, cx, dx; – Big-endian: Bytes are stored in “natural” order (the } word; leftmost byte comes first). struct { BYTE al, ah, bl, bh, cl, ch, dl, dh; – Little-endian: Bytes are stored in reverse order (the } byte; lfleftmost b yte comes l ast) . } regs; • x86 processors use little-endian order.

52 Copyright © 2008 W. W. Norton & Company. 54 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Using Unions to Provide Multiple Views of Data Program: Viewing Memory Locations • WdWe don’t normall y needt o worry ab outb tbtyte • The viewmemory.c program allows th e user t o ordering. view segments of computer memory. • However, programs that deal with memory at a • The program first displays the address of its own low level must be aware of the order in which main function as well as the address of one of its bytes are stored. variables. • It’s also relevant when working with files that •The ppgrogram next prom pts the user to enter an contain non-character data. address (as a hexadecimal integer) plus the number of bytes to view. • The program then displays a block of bytes of the chosen length, starting at the specified address.

55 Copyright © 2008 W. W. Norton & Company. 57 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Using Pointers as Addresses Program: Viewing Memory Locations • AddfththAn address often has the same numb er of fbit bits as • By tes are di spl ayedi d in groups of10( f 10 (exceptf t for th e an integer (or long integer). last group). • Creating a pointer that represents a specific • Bytes are shown both as hexadecimal numbers address is done by casting an integer to a pointer: and as characters. BYTE *p; • Only printing characters are displayed; other p = (BYTE*) 0x1000; characters are shown as periods. /* p contains address 0x1000 */ • The program assumes that int values and addresses are stored using 32 bits. • Addresses are displayed in hexadecimal.

56 Copyright © 2008 W. W. Norton & Company. 58 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming

ptr = (BYTE *) a ddr; viewmemory.c for (; n > 0; n -= 10) { /* Allows the user to view regions of computer memory */ printf("%8X ", (unsigned int) ptr); for (i = 0; i < 10 && i < n; i++) #include printf("%.2X ", *(ptr + i)); #include for (; i < 10; i++) printf("" ); typedef unsigned char BYTE; printf(" "); for (i = 0; i < 10 && i < n; i++) { int main(void) BYTE ch = *(ptr + i ); { if (!isprint(ch)) unsigned int addr; ch = '.'; int i, n; printf("%c", ch); BYTE *ptr; } printf("\n"); printf("Address of main function: %x\n", (unsigned int) main); ptr += 10; printf("Address of addr variable: %x\n", (unsigned int) &addr); } return 0; }

59 Copyright © 2008 W. W. Norton & Company. 61 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming

prin tf("\nEtEnter a (h)dd(hex) address: "); scanf("%x", &addr); Program: Viewing Memory Locations printf("Enter number of bytes to view: "); scanf(" %d", &n); • SlttiGCC86tSample output using GCC on an x86 system runni iLing Linux: Address of main function: 804847c printf("\n"); Address of addr variable: bff41154 printf(" Address Bytes Characters\nn);"); printf(" ------\n"); Enter a (hex) address: 8048000 Enter number of bytes to view: 40 Address B yt es Ch arac ters ------8048000 7F 45 4C 46 01 01 01 00 00 00 .ELF...... 804800A 00 00 00 00 00 00 02 00 03 00 ...... 8048014 01 00 00 00 C0 83 04 08 34 00 ...... 4. 804801E 00 00 C0 0A 00 00 00 00 00 00 ...... • The 7F byte followed by the letters E, L, and F identify the format (ELF) in which the executable file was stored.

60 Copyright © 2008 W. W. Norton & Company. 62 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming Program: Viewing Memory Locations The volatile Type Qualifier • A sample that displays bytes starting at the address of addr: • The voltillatile type qualifi er all ows us t o i nf orm Address of main function: 804847c Address of addr variable: bfec5484 the compiler if any of the data used in a program Enter a (hex) address: bfec5484 is vol atil e. Enter number of bytes to view: 64 • volatile typically appears in the declaration of Address B yt es Ch arac ters ------a pointer variable that will point to a volatile BFEC5484 84 54 EC BF B0 54 EC BF F4 6F .T...T...o BFEC548E 68 00 34 55 EC BF C0 54 EC BF h.4U...T.. memory location: BFEC5498 08 55 EC BF E3 3D 57 00 00 00 .U...=W... volatile BYTE *p; BFEC54A2 00 00 A0 BC 55 00 08 55 EC BF ....U..U.. BFEC54AC E3 3D 57 00 01 00 00 00 34 55 .=W.....4U /* p will point to a volatile byte */ BFEC54B6 EC BF 3C 55 EC BF 56 11 55 00 ..

63 Copyright © 2008 W. W. Norton & Company. 65 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 20: Low-Level Programming The volatile Type Qualifier The volatile Type Qualifier • OttiltiOn some computers, certain memory locations are • SthtSuppose that p point s t o a memory l ocati on th at “volatile.” contains the most recent character typed at the • The value stored at such a location can change as a user’k’s key boar d. program is running, even though the program • A loop that obtains characters from the keyboard itself isn’t storing new values there. and stores them in a buffer array: • For examppygle, some memory locations might hold while (buffer not full) { data coming directly from input devices. for input; buffer[i] = *p; if (buffer[i++] == '\n') break; }

64 Copyright © 2008 W. W. Norton & Company. 66 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 20: Low-Level Programming Chapter 21: The Standard Library The volatile Type Qualifier • A sop histi cat ed compil er mi ght noti ce th at this loop changes neither p nor *p. • It could optimize the program by altering it so that Chapter 21 *p is fetched just once: store *p in a register; while (buffer not full) { The Standard Library waifit for i nput; buffer[i] = value stored in register; if (buffer[i++] == '\nn)') break; }

67 Copyright © 2008 W. W. Norton & Company. 1 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 20: Low-Level Programming Chapter 21: The Standard Library The volatile Type Qualifier Using the Library • The opti mi zed program will fill the b uff er with • ThC89tThe C89 stand ard dlib library i s di diiddit15videdinto 15 part s, many copies of the same character. with each part described by a header. • Declaring that p points to volatile data avoids this • C99 has an additional nine headers. problem by telling the compiler that *p must be fetched from memory each time it’s needed.

†C99 only

68 Copyright © 2008 W. W. Norton & Company. 2 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 21: The Standard Library Chapter 21: The Standard Library Using the Library Restrictions on Names Used in the Library • Mos t comp ilers come with a more ext ensi ve • Any file th ati t incl ud es a st and ardh d er must ob ey library that has additional (nonstandard) headers. two rules: • Nonstandard headers often provide: – The names of macros defined in that header can’t be – Functions that are specific to a particular computer or used for any other purpose. operating system – Library names with file scope ( tdftypedef names, in – Functions that allow more control over the screen and particular) can’t be redefined at the file level. kbkeyboar d – Support for graphics or a window-based user interface

3 Copyright © 2008 W. W. Norton & Company. 5 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 21: The Standard Library Chapter 21: The Standard Library Using the Library Restrictions on Names Used in the Library • The st and ardh d head ers consi st pri maril y off f functi on • Other rest ri cti ons are l ess ob vi ous: prototypes, type definitions, and macro – Identifiers that begin with an underscore followed by dfiitidefinitions. an upper-case lttletter or a second und erscore are • When a file includes several standard headers, the reserved for use within the library. order of #include directives doesn’t matter. – Identifiers that begin with an underscore are reserved for use as identifiers and tags with file scope. • It’s also legal to include a standard header more – Every identifier with external linkage in the standard than once. library is reserved for use as an identifier with external linkage. In particular, the names of all standard library functions are reserved.

4 Copyright © 2008 W. W. Norton & Company. 6 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 21: The Standard Library Chapter 21: The Standard Library Restrictions on Names Used in the Library Functions Hidden by Macros • These rul es appl y t o every file i n a program, •gethtchar is a lib rary f uncti on d ecl aredi d in th e regardless of which headers the file includes. header: • Moreover, they apply not just to names that are int getchar(void); currently used in the library, but also to names that • usually defines getchar as a are set aside for future use. macro as well: • For examppgle, C reserves identifiers that begin with #define getchar() getc(stdin) str followed by a lower-case letter. • By default, a call of getchar will be treated as a macro invocation.

7 Copyright © 2008 W. W. Norton & Company. 9 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 21: The Standard Library Chapter 21: The Standard Library Functions Hidden by Macros Functions Hidden by Macros • The C st and ard all ows h ead ers t o d efi ne macros • A macro is usua lly pref erabl e t o a t rue f uncti on, that have the same names as library functions, but because it will probably improve the speed of a requithttftibires that a true function be avail ilblable as well . program. • It’s not unusual for a library header to declare a • Occasionally, a genuine function is needed, function and define a macro with the same name. perhaps to minimize the size of the executable code.

8 Copyright © 2008 W. W. Norton & Company. 10 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 21: The Standard Library Chapter 21: The Standard Library Functions Hidden by Macros C89 Library Overview • A macro de fin ition can b e removed (thus gai ni ng Diagnosti cs access to the true function) by using #undef: Contains only the assert macro, which can be #include used to insert self-checks into a program. If any #undef getchar check fails, the program terminates. • ##undef hffhihas no effect when given a name th h’at’s Character Handling not defined as a macro. Prov ides fu nctions for classify ing characters and for converting letters from lower to upper case or vice versa.

11 Copyright © 2008 W. W. Norton & Company. 13 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 21: The Standard Library Chapter 21: The Standard Library Functions Hidden by Macros C89 Library Overview • In divid ual uses of a macro can b e di sabl edb d by Errors putting parentheses around its name: Provides errno (“error number”), an lvalue that ch = (getchar)(); can be tested after a call of certain library /* instead of ch = getchar(); */ functions to see if an error occurred. •Th’idhe preprocessor can’t spot a parameterized Characteristics of Floating Types macro unless its name is followed by a left parenthihesis. Prov ides macros that describe the characteristics • However, the compiler can still recognize of floating types, including their range and getchar as a function. accuracy.

12 Copyright © 2008 W. W. Norton & Company. 14 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 21: The Standard Library Chapter 21: The Standard Library C89 Library Overview C89 Library Overview Sizes ofI f In teger T ypes l.h> SignalH l Handli ng Provides macros that describe the characteristics Provides functions that deal with exceptional of integer types (including character types), conditions (signals). including their maximum and minimum values. – The function installs a function to be called if a given signal should occur later. Localization – The raise function causes a signal to occur. Prov ides fu nctions to help a program adapt its behavior to a country or other geographic region. Variable Arguments Provides tools for writing functions that can have a variable number of arguments.

15 Copyright © 2008 W. W. Norton & Company. 17 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 21: The Standard Library Chapter 21: The Standard Library C89 Library Overview C89 Library Overview MthMathema tics Common D e fin itions Provides common mathematical functions. Provides definitions of frequently used types and macros. Nonlocal Jumps Provides the setjmp and longjmp functions. Input/Output setjmp “marks” a place in a program; longjmp Provides a large assortment of input/output can then be used to return to that place later. fu nctions, incl uding operations on both sequ ential and random-access files.

16 Copyright © 2008 W. W. Norton & Company. 18 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 21: The Standard Library Chapter 21: The Standard Library C89 Library Overview C99 Library Changes Genera l Utilities • Some o ffth the bi ggest ch anges i n C99 aff ectth t the Provides functions that perform the following standard library: operations: – Additional headers. The C99 standard library has nine – Converting strings to numbers headers that don’t exist in C89. – Generating pseudo-random numbers – Additional macros andf d functi ons. C99 a dds macros and functions to several existing headers (especially – Performing memory management tasks ). – Communicating with the operating system – Enhanced versions of existing functions. Some – Searching and sorting existingg,g functions, including printf and scanf, – Performing conversions between multibyte characters have additional capabilities in C99. and wide characters

19 Copyright © 2008 W. W. Norton & Company. 21 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 21: The Standard Library Chapter 21: The Standard Library C89 Library Overview C99 Library Changes Stri ng H andli ng Comp A rith meti c Provides functions that perform string operations, Defines the complex and I macros. as well as functions that operate on arbitrary Provides functions for performing mathematical blocks of memory. oppperations on complex numbers. Date and Time Floating-Point Environment Prov ides fu nctions for determining the time (and Provides access to fl oati ng-poifldint status flags and date), manipulating times, and formatting times control modes. for display.

20 Copyright © 2008 W. W. Norton & Company. 22 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 21: The Standard Library Chapter 21: The Standard Library C99 Library Changes C99 Library Changes FtCifFormatConversion of Type-GiMthGeneric Math Integer Types Provides “type-generic” macros that can detect Defines macros th at can b e usedi d in f ormat stri ngs argument types and substitute a call of a for input/output of the integer types declared in or function. . Extended Multibyte and Provides functions for working with greatest- Wide-Character Utilities width integers. Provides functions for wide-character input/output Alternative Spellings and wide string manipulation. Defines macros representing the operators whose symbols contain the characters &, |, ~, !, and ^.

23 Copyright © 2008 W. W. Norton & Company. 25 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 21: The Standard Library Chapter 21: The Standard Library C99 Library Changes C99 Library Changes BlBoolean T ype andV dVlalues Wide-Charact er Cl assifi ca tion Defines the bool, true, and false macros, as and Mapping Utilities well as a macro that can be used to test whether The wide-character version of . these macros have been defined. Provides functions for classifyyging and chang gging Integer Types the case of wide characters. Declares integer types with specified widths and defines related macros. Defines parameteri zed macros th at construct integer constants with specific types.

24 Copyright © 2008 W. W. Norton & Company. 26 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 21: The Standard Library Chapter 21: The Standard Library The Header (C99): The Header: Common Definitions Boolean Type and Values • TdfidiTypes definedin : • Macros defined in : – ptrdiff_t. The type of the result when two pointers bool (defined to be _Bool) are subtract ed . true (defined to be 1) – size_t sizeof . The type returned by the operator. false (defined to be 0) –wchthar_t . Atype large enought o represent all __bool_true_false_are_defined (defined to be 1) possible characters in all supported locales. •A ppgrogram could use a pppreprocessing directive to • MdfidiMacros definedin : test the last of these before attempting to define its – NULL. Represents the null pointer. own version of bool, true, or false. – offsetof. ChbfbbComputes the number ofbytes between the beginning of a structure and one of its members.

27 Copyright © 2008 W. W. Norton & Company. 29 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 21: The Standard Library Chapter 22: Input/Output The Header: Common Definitions • AlttAn example structure: struct s { char a; int b[2]; Chapter 22 float c; }; • The value of offsetof(struct s, a) must be 0, Input/Output but the offsets of b and c depend on the compiler. • One possibility is that offsetof(struct s, b) is 1, and offsetof(struct s, c) is 9. • If a compiler should leave a three-byte hole after a, the off set s of b and c would be 4 and12 d 12.

28 Copyright © 2008 W. W. Norton & Company. 1 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Introduction Introduction • C’iC’s input/ t/ttlibithbitoutput library is the biggest and most • IC99In C99, some I/OfI/O func tions b blelong t ttho the important part of the standard library. header. •The header is the primary repository •The functions deal with wide of input/output functions, including printf, characters rather than ordinary characters. scanf, putchar, getchar, puts, and gets. • Functions in that read or write data •This chapppter provides more information about are known as byypte input/outp pfut functions. these six functions. • Similar functions in are called wide- • It also introduces many new functions, most of character input/output functions. which deal with files.

2 Copyright © 2008 W. W. Norton & Company. 4 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Introduction Streams • TitbTopics to be covered : • ICthtIn C, the term stream means any source ofinput – Streams, the FILE type, input and output redirection, or any destination for output. anddth the diff erence b et ween t ext files andbi d binary fil es • Many small programs obtain all their input from – Functions designed specifically for use with files, one stream (the keyboard) and write all their including functions that open and close files output to another stream (the screen). – Functions that perform “formatted” input/output • Larggpger programs may need additional streams. – Functions that read and write unformatted data (characters, lines, and blocks) • Streams often represent files stored on various – Random access operations on files media. – Functions that write to a string or read from a string • However, they could just as easily be associated with devices such as network ports and printers.

3 Copyright © 2008 W. W. Norton & Company. 5 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output File Pointers Standard Streams and Redirection • AiAccessing a st ream i idthhs done through a file poi nt er, • The I/O functi ons di scusse ddi in previ ous ch apt ers which has type FILE *. obtain input from stdin and send output to •The FILE type is declared in . stdou t. • Certain streams are reppypresented by file pointers • Many operating systems allow these default with standard names. meanings to be changed via a mechanism known • Additional file pointers can be declared as needed: as redirection. FILE *fp1, *fp2;

6 Copyright © 2008 W. W. Norton & Company. 8 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Standard Streams and Redirection Standard Streams and Redirection • provides th ree st and ard st reams: • Atypi calt ech ni que f or f orci ng a program t o File Pointer Stream Default Meaning obtain its input from a file instead of from the stdin SddiStandardinput KbKeyboar d kbkeyboar d: stdout Standard output Screen demo out.dat All data written to stdout will now go into the out.dat file instead of appearing on the screen.

7 Copyright © 2008 W. W. Norton & Company. 9 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Standard Streams and Redirection Text Files versus Binary Files • ItditidttditibInput redirection and output redirection can be • supporttts two ki kidnds of ffil files: t ext and combined: binary. demo out.dat • The bytes in a text file represent characters, •The < and > characters don’t have to be adjacent allowing humans to examine or edit the file. to file names, and the order in which the redirected – The source code for a C program is stored in a text file. files are listed doesn’t matter: •In a binaryfile, byyyptes don’t necessarily represent demo < in.dat > out.dat characters. demo >out.dat

10 Copyright © 2008 W. W. Norton & Company. 12 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Standard Streams and Redirection Text Files versus Binary Files • One pro blem with out put redi recti on i s th at • Text files h ave t wo ch aract eri sti cs th atbi t binary fil es everything written to stdout is put into a file. don’t possess. • Writing error messages to stderr instead of • Text files are divided into lines. Each line in a text stdout guarantees that they will appear on the file normally ends with one or two special screen even when stdout has been redirected. characters. – Windows: carriage-return character ('\x0d') followed by line-feed character ('\x0a') – UNIX and newer versions of Mac OS: line-feed character – Older versions of Mac OS: carriage-return character

11 Copyright © 2008 W. W. Norton & Company. 13 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Text Files versus Binary Files Text Files versus Binary Files • TtfilText files may cont tiain a speci il“dal“end-of-file” • The oth er opti on i s t o st ore th e numb er i n bi nary, marker. which would take as few as two bytes: – IWidIn Windows, th e mark er i s '\x1a' (Ctrl -Z), b ut i t i s not required. – Mos t oth er operati ng syst ems, i ncl udi ng UNIX , h ave no special end-of-file character. • Storing numbers in binary can often save space. • In a binary fil e, th ere are no end -of-line or end -of- file markers; all bytes are treated equally.

14 Copyright © 2008 W. W. Norton & Company. 16 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Text Files versus Binary Files Text Files versus Binary Files • When d at a i s writt en t o a fil e, it can b e st oredi d in • Programs tha t readf d from a fil e or writ e t o a fil e text form or in binary form. must take into account whether it’s text or binary. • One way to store the number 32767 in a file would • A program that displays the contents of a file on be to write it in text form as the characters 3, 2, 7, the screen will probably assume it’s a text file. 6, and 7: • A file-copying program, on the other hand, can’t assume that the file to be copied is a text file. – If it does, binary files containing an end-of-file character won’t be copied completely. • When we can’t say for sure whether a file is text or binary, it’s safer to assume that it’s binary .

15 Copyright © 2008 W. W. Norton & Company. 17 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output File Operations Opening a File • Simp lic ity i s one ofth f the att rac tions ofi f input and • The word restittrict appears titwice i ithn the output redirection. prototype for fopen. • Unfortunately, redirection is too limited for many • restrict, which is a C99 keyword, indicates applications. that filename and mode should point to strings – When a program relies on redirection, it has no control that don’t share memory locations. over its files; it doesn’t even know their names. • The C89 prototype for fopen doesn’t contain – Redirection doesn’t help if the program needs to read restrict but is otherwise identical. from two files or write to two files at the same time. • restrict has no effect on the behavior of • When redirection isn’t enough, we’ll use the file fopen, so it can usually be ignored. operations that provides.

18 Copyright © 2008 W. W. Norton & Company. 20 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Opening a File Opening a File • OiOpening a fil filfe for use as a st ream requi res a call llf of • In Wi nd ows, b e caref ul wh en th e fil e name i n a call of the fopen function. fopen includes the \ character. • Prototype for fopen: • The call FILE *fopen(const char * restrict filename, fopen("c:\project\test1.dat", "r") const char * restrict mode); will fail , b ecause \t itis treat tded as a ch aract er escape. • filename is the name of the file to be opened. • One way to avoid the problem is to use \\ instead of \: – This argument may include information about the file’s fopen("c:\\project\\test1.dat", "r") location, such as a drive specifier or path. • An alternative is to use the / character instead of \: • mode is a “mode string” that specifies what fopen("c:/project/test1.dat", "r") operations we intend to perform on the file.

19 Copyright © 2008 W. W. Norton & Company. 21 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Opening a File Modes • fopen returns a fil e poi nt er th atth t the program can • MdMode s titrings f or t ext tfil files: (and usually will) save in a variable: String Meaning fp = fopen("in.dat", "r"); """r" OfOpen for rea ding /* opens in.dat for reading */ "w" Open for writing (file need not exist) "a" Oppppg(en for appending(file need not exist ) • When i t can’ t open a fil e, fopen returns a null "r+" Open for reading and writing, starting at beginning pointer. "w+" Open for reading and writing (truncate if file exists) """a+" Open for rea ding an d wr iting( (appen d if file exi st s)

22 Copyright © 2008 W. W. Norton & Company. 24 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Modes Modes • FtFactors th thtdtatdetermi ne whi hihch mod e st titring to pass • MdMode s titrings f or bi nary fil es: to fopen: String Meaning – Which operations are to be performed on the file "rb" OfOpen for rea ding "wb" Open for writing (file need not exist) – Whether the file contains text or binary data "ab" Oppppg(en for appending(file need not exist ) "r+b" or "rb+" Open for reading and writing, starting at beginning "w+b" or "wb+" Open for reading and writing (truncate if file exists) "a+b" or "ab+" Open for rea ding an d wr iting( (appen d if file exi st s)

23 Copyright © 2008 W. W. Norton & Company. 25 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Modes Closing a File • No te thatth t there are diff erent mod e st ri ngs f or • The flfclose ftillfunction allows a program t tlo close a writing data and appending data. file that it’s no longer using. • When data is written to a file, it normally • The argument to fclose must be a file pointer overwrites what was previously there. obtained from a call of fopen or freopen. • When a file is opened for appending, data written • fclose returns zero if the file was closed to the file is added at the end. successfully. • Otherwise, it returns the error code EOF (a macro defined in ).

26 Copyright © 2008 W. W. Norton & Company. 28 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Modes Closing a File • SillSpecial rules appl lhy when a fil filie is openedf dfbthor both • The outli ne of a program th at opens a fil e f or readi ng: reading and writing. #include #include – Can’t switch from reading to writing without first #define FILE_NAME "example.dat" calling a file-positioning function unless the reading int main(void) operation encountered the end of the file. { FILE *fp; – Can’t switch from writing to reading without either calling fflush or calling a file-positioning function. fp = fopen(FILE_NAME, "r"); if (fp == NULL) { printf("Can't open %s\n", FILE_NAME); exit(EXIT_FAILURE); } … fclose(fp); return 0; }

27 Copyright © 2008 W. W. Norton & Company. 29 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Closing a File Attaching a File to an Open Stream • It’s no t unusua llt to see th e call of fopen • freopen’ltliitthid’s normal return value is its third combined with the declaration of fp: argument (a file pointer). FILE *fp = fopen(FILE_NAME, "r"); • If it can’t open the new file, freopen returns a or the test against NULL: null pointer. if ((fp = fopen(FILE_NAME, "r")) == NULL) …

30 Copyright © 2008 W. W. Norton & Company. 32 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Attaching a File to an Open Stream Attaching a File to an Open Stream • freopen attach es a diff erent file t o a st ream • C99 add s a new t wi st : if filename illis a null that’s already open. pointer, freopen attempts to change the stream’s • The most common use of freopen is to mode t o th at specifi edb d by th e mode parameter. associate a file with one of the standard streams • Implementations aren’t required to support this (stdin, stdout, or stderr). feature. • A call of freopen that causes a program to begin • If theyyyyp do, they mayplace restrictions on which writing to the file foo: mode changes are permitted. if (freopen("foo", "w", stdout) == NULL) { /* error; foo can't be opened */ }

31 Copyright © 2008 W. W. Norton & Company. 33 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output

Obtaining File Names from the Command Line Obtaining File Names from the Command Line • There are several ways t o suppl y fil e names t o a • argv[0] poitints t o th e program name, argv[1] program. through argv[argc-1] point to the remaining – Building file names into the program doesn’t provide arguments, and argv[argc] is a null pointer. much flexibility. •In the demo example, argc is 3 and argv has the – PtithttfilPrompting the user to enter file names can b bkde awkward. fllfollowi ng appearance: – Having the program obtain file names from the command line is often the best solution. • An example that uses the command line to supply two file names to a program named demo: demo names.dat dates.dat

34 Copyright © 2008 W. W. Norton & Company. 36 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Program: Checking Whether Obtaining File Names from the Command Line a File Can Be Opened • Chapt er 13 sh owedh d how t o access command -line •The canopen.c program determines if a file arguments by defining main as a function with exists and can be opened for reading. tttwo parameters: • The user will give the program a file name to int main(int argc, char *argv[]) check: { … canopen file } • The program will then print either file can be • argc is the number of command-line arguments. opened or file can't be opened. • argv is an array of pointers to the argument • If the user enters the wrong number of arguments strings. on the command line, the program will print the message usage: canopen filename.

35 Copyright © 2008 W. W. Norton & Company. 37 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output canopen.c Temporary Files /* Checks whether a file can be opened for reading */ #include • tfiltmpfile creatttes a temporary fil fil(die (openedin #include "wb+" mode) that will exist until it’s closed or int main(int argc, char * argv[]) { the program end s. FILE *fp; • A call of tmpfile returns a file pointer that can if (ar gc != 2 )){ { printf("usage: canopen filename\n"); be used to access the file later: exit(EXIT_FAILURE); } FILE *tempptr; if ((fp = fopen(argv[1], "r")) == NULL) { … printf("%s can't be opened\n", argv[1]); tempptr = tmpfile(); exit(EXIT_FAILURE); } /* creates a temporary file * / printf("%s can be opened\n", argv[1]); • If it fails to create a file, tmpfile returns a null fclose(fp); return 0; } pointer.

38 Copyright © 2008 W. W. Norton & Company. 40 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Temporary Files Temporary Files • PftdtttfilPrograms often needto create temporary files— • DbkfiDrawbacks of using tmp file: files that exist only as long as the program is – Don’t know the name of the file that tmpfile creates. running. – Can’t decide later to make the file permanent. • provides two functions, tmpfile • The alternative is to create a temporary file using and tmpnam, for working with temporary files. fopen. •The tmpnam function is useful for ensuring that this file doesn’t have the same name as an existing file.

39 Copyright © 2008 W. W. Norton & Company. 41 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Temporary Files Temporary Files • tmpnam generatftfiltes a name for a temporary file. • The TMP_ MAX macro (de finedi d in ) • If its argument is a null pointer, tmpnam stores specifies the maximum number of temporary file the file name in a static variable and returns a names that can b e generat edb d by tmpnam. pointer to it: • If it fails to generate a file name, tmpnam returns char *filename; a null pointer. … filename = tmpnam(NULL); /* creates a temporary file name */

42 Copyright © 2008 W. W. Norton & Company. 44 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Temporary Files File Buffering • Otherwi se, tmpnam copithfilies the file name i itnto a • TfidttfTransferring data to or from a di dikdiiskdrive is a character array provided by the programmer: relatively slow operation. char filename[L_tmpnam]; • The secret to achieving acceptable performance is … buffering. tmpnam(filename); /* creates a temporary file name */ • Data written to a stream is actually stored in a • In this case, tmpnam also returns a pointer to the buffer area in memoryy(; when it’s full (or the first character of this array. stream is closed), the buffer is “flushed.” • L_ tmpnam is a macro in that • Input streams can be buffered in a similar way: the specifies how long to make a character array that buffer contains data from the input device; input is will hold a temporary file name. read from this buffer instead of the device itself.

43 Copyright © 2008 W. W. Norton & Company. 45 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output File Buffering File Buffering • BffiBuffering can result lti in enormous gai ns i n •setbftvbuf allows us t o ch ange th e way a st ream i s efficiency, since reading a byte from a buffer or buffered and to control the size and location of the stitoring a b btiyte in a b bffiuffer is very f ftast. bffbuffer. • It takes time to transfer the buffer contents to or • The function’s third argument specifies the kind of from disk, but one large “block move” is much buffering desired: faster than many tiny byte moves. _IOFBF (full buffering) • The functions in perform buffering _IOLBF (line buffering) automaticallyyg when it seems advantageous. _IONBF (no buffering) • On rare occasions, we may need to use the • Full buffering is the default for streams that aren’t functions fflush, setbuf, and setvbuf. connected to interactive devices.

46 Copyright © 2008 W. W. Norton & Company. 48 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output File Buffering File Buffering • By calli ng fflus h, a program can flus h a file’ s •setbftvbuf’s second argument (if it’s not a null buffer as often as it wishes. pointer) is the address of the desired buffer. • A call that flushes the buffer for the file associated • The buffer might have static storage duration, with fp: automatic storage duration, or even be allocated fflush(fp); /* flushes buffer for fp */ dynamically. • A call that flushes all output streams: • setvbuf’s last argument is the number of bytes fflush(NULL); /* flushes all buffers */ in the buffer. • fflush returns zero if it’ s successful and EOF if an error occurs.

47 Copyright © 2008 W. W. Norton & Company. 49 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output File Buffering File Buffering • AllfA call of setbftvbuf that ch anges th e b uff eri ng of •setbu f is an old er f uncti on th at assumes d ef ault stream to full buffering, using the N bytes in the values for the buffering mode and buffer size. bffbuffer array as the b u ffer: • If buf is a null pointer, the call char buffer[N]; setbuf(stream, buf) is equivalent to … (void) setvbuf(stream, NULL, _IONBF, 0); setvbuf(stream, buffer, _IOFBF, N); • setvbuf must be called after stream is opened • Otherwise, it’s equivalent to but before any other operations are performed on (void) setvbuf(stream, buf, _IOFBF, BUFSIZ); it. where BUFSIZ is a macro defined in . • setbuf is considered to be obsolete.

50 Copyright © 2008 W. W. Norton & Company. 52 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output File Buffering Miscellaneous File Operations • It’s al so l egalt l to call setbftvbuf with a null poi nt er • The remove and rename ftillfunctions allow a as the second argument, which requests that program to perform basic file management setbftvbuf create a b uff er w ith the specifi ed si ze. operations. • setvbuf returns zero if it’s successful. • Unlike most other functions in this section, • It returns a nonzero value if the mode argument is remove and rename work with file names invalid or the request can’t be honored. instead of file pointers. • Both functions return zero if they succeed and a nonzero value if they fail.

51 Copyright © 2008 W. W. Norton & Company. 53 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Miscellaneous File Operations Formatted I/O • remove dltdeletes a fil e: • The next group of library f uncti ons use f ormat remove("foo"); strings to control reading and writing. /*dlt/* deletes th thfile file named"f d"f"*/oo"*/ • printf and related functions are able to convert • If a program uses fopen (instead of tmpfile) data from numeric form to character form during to create a temporary file, i t can use remove to output. delete the file before the program terminates. • scanf and related functions are able to convert • The effect of removing a file that’s currently open data from character form to numeric form during is implementation-defined. input.

54 Copyright © 2008 W. W. Norton & Company. 56 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Miscellaneous File Operations The …printf Functions • rename chthffilhanges the name of a file: • The fitffprintf and pritfintf functions write a variable rename("foo", "bar"); number of data items to an output stream, using a format /* renames "f oo ""t to "bar ""*/ */ string to control the appearance of the output. • rename is handy for renaming a temporary file • The prototypes for both functions end with the ... createdid using fopen if a program sh ould decid e symbol (an ellipsis), which indicates a variable number of additional arguments: to make it permanent. int fprintf(FILE * restrict stream, – If a file with the new name already exists, the effect is const char * restrict format, ...); implementation-defined. int printf(const char * restrict format, ...); • rename may filiffail if ask kded to rename an open fil e. • Both functi ons ret urn th e numb er of ch aract ers writt en; a negative return value indicates that an error occurred.

55 Copyright © 2008 W. W. Norton & Company. 57 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output The …printf Functions The …printf Functions •pritfintf alittlways writes to stdou t, whereas • TthftiiTwo other functions in can write fprintf writes to the stream indicated by its formatted output to a stream. first argument : • These functions, named vfprintf and printf("Total: %d\n", total); vprintf, are fairly obscure. /* wr ites to s tdou tt*/ */ • Both rely on the va_list type, which is declared fprintf(fp, "Total: %d\n", total); in , so they’re discussed along with /* writes to fp */ that header. • A call of printf is equivalent to a call of fitffprintf with stdou t as the fi rst argument .

58 Copyright © 2008 W. W. Norton & Company. 60 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output The …printf Functions …printf Conversion Specifications • fitffprintf works with any out put st ream. • BthBoth pritfintf and fitffprintf requifire a format • One of its most common uses is to write error string containing ordinary characters and/or messages to stderr: conversiifitiion specifications. fprintf(stderr, "Error: data file can't be opened.\n"); – Ordinary characters are printed as is. • Writing a message to stderr guarantees that it – Conversion specifications describe how the remaining will appear on the screen even if the user redirects arguments are to be converted to character form for stdout. display.

59 Copyright © 2008 W. W. Norton & Company. 61 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output …printf Conversion Specifications …printf Conversion Specifications • A …pritfintf conversiifitiitfion specification consists of • Mini mum fi eld width (opti onal) . A n it em th at’ s the % character, followed by as many as five too small to occupy the field will be padded. dis tinctit t items: – By default, spaces are added to the left of the item. • An item that’s too large for the field width will still be displayed in its entirety. • The field width is either an integer or the character *. – If * is present, the field width is obtained from the next argument.

62 Copyright © 2008 W. W. Norton & Company. 64 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output …printf Conversion Specifications …printf Conversion Specifications • Flags (op tional ; more th an one permitt e d): • PiiPrecision (til)Th(optional). The meani ng ofth e preci iision Flag Meaning depends on the conversion: - LftLeft-justify tif withi n fi eld . d, i, o, u, x, X:mini mum numb er ofdi f dig its (l eadi ng zeros are + Numbers produced by signed conversions always begin with added if the number has fewer digits) + or -. a, A, e, E, f, F: number of digits after the decimal point space Nonnegative numbers produced by signed conversions are g, G: number of significant digits preceded by a space. s: maximum number of bytes # Octal numbers begin with 0, nonzero hexadecimal numbers with 0x or 0X. Floating-point numbers always have a • The precision is a period (.) followed by an integer decimal point. Trailing zeros aren’t removed from numbers or the character *. printed with the g or G conversions. – If * is present, the precision is obtained from the next 0 Numbers are padded with leading zeros up to the field width. argument. ()(zero)

63 Copyright © 2008 W. W. Norton & Company. 65 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output …printf Conversion Specifications …printf Conversion Specifications Length • LthdifiLength modifier (op tional) . I ndi cat es th atth t the it em Modifier Conversion Specifiers Meaning to be displayed has a type that’s longer or shorter ll† d, i, o, u, x, X long long int, than normal . (ll(ell-ell) unsidigned long long int –%dnormally refers to an int value; %hd is used to n long long int * † display a shthort itint and %ld is used to display a j d, i, o, u, x, X intmax_ t, uintmax_ t n intmax_t * long int. z† d, i, o, u, x, X size_t nsize_t * t† d, i, o, u, x, X ptrdiff_t n ptrdiff_ t * La, A, e, E, f, F, g, G long double †C99 only

66 Copyright © 2008 W. W. Norton & Company. 68 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output …printf Conversion Specifications …printf Conversion Specifications Length Modifier Conversion Specifiers Meaning • CiConversion specifier. MtbMustbe one ofth e hh† d, i, o, u, x, X signed char, unsigned char characters in the following table. nsidigned char * Conversion hd, i, o, u, x, X short int, unsigned short int Specifier Meaning n short int * d, i Converts an int value to decimal form. ld, i, o, u, x, X long int, unsigned long int o, u, x, X Converts an unsigned int value to base 8 (o), base (ell) n long int * 10 (u), or base 16 (x, X). x displays the hexadecimal cwint_t digits a–f in lower case; X displays them in upper case. † s wchar_t * f, F Converts a double value to decimal form, putting the decimal point in the correct position. If no precision is a, A, e, E, f, F, g, G no effect specified, displays six digits after the decimal point. †C99 only †C99 only

67 Copyright © 2008 W. W. Norton & Company. 69 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output C99 Changes to …printf …printf Conversion Specifications Conversion Specifications Conversion Specifier Meaning • C99 changes to the conversion specifications for e, E Converts a double value to scientific notation. If no printf and fprintf: precision is specified, displays six digits after the decimal point. If e is chosen, the exponent is preceded – Additional length modifiers by the letter e; if E is chosen, the exponent is preceded – Additional conversion specifiers by E. g, Ggconverts a double value to either f form or e form. – Ability to write infinity and NaN G chooses between F and E forms. – Support for wide characters a†, A† Converts a double value to hexadecimal scientific – Previously undefined conversion specifications now notation using the form [-]0xh.hhhhp±d. a displays the hex digits a–f in lower case; A displays them in allowed upper case. The choice of a or A also affects the case of the letters x and p. †C99 only

70 Copyright © 2008 W. W. Norton & Company. 72 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Examples of …printf …printf Conversion Specifications Conversion Specifications Conversion Specifier Meaning • Examples showing the effect of flags on the %d c Displays an int value as an unsigned character. conversion: s Writes the characters pointed to by the argument. Stops CiConversion RlfAliResult ofApplying RlfAliResult ofApplying writing when the number of bytes specified by the Specification Conversion to 123 Conversion to –123 precision (if present) is reached or a null character is %8d •••••123 ••••-123 encountered. %-8d 123••••• -123•••• p Converts a void * value to printable form. %+8d ••••+123 ••••-123 n The corresponding argument must point to an object of type int. Stores in this object the number of characters % 8d •••••123 ••••-123 written so far by this call of …printf; produces no %08d 00000123 -0000123 output. %-+8d +123•••• -123•••• % Writes the character %. %- 8d •123•••• -123•••• %+08d +0000123 -0000123 % 08d •0000123 -0000123 71 Copyright © 2008 W. W. Norton & Company. 73 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Examples of …printf Examples of …printf Conversion Specifications Conversion Specifications • Examples showing the effect of the # flag on the o, x, •Examplhihhles showing how the %g conversidilion displays some X, g, and G conversions: numbers in %e form and others in %f form: Result of Applying %.4g Conversion Result of Applying Result of Applying Number Conversion to Number Specification Conversion to 123 Conversion to 123.0 123456. 1.235e+05 %8o •••••173 12345.6 1.235e+04 %#8o ••••0173 1234.56 1235 %8x ••••••7b 123.456 123.5 %#8x ••••0x7b 12.3456 12.35 %8X ••••••7B 1.23456 1.235 .123456 0.1235 %#8X ••••0X7B .0123456 0.01235 %8g •••••123 .00123456 0.001235 %#8g •123.000 .000123456 0.0001235 %8G •••••123 .0000123456 1.235e-05 %#8G •123.000 .00000123456 1.235e-06

74 Copyright © 2008 W. W. Norton & Company. 76 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Examples of …printf Examples of …printf Conversion Specifications Conversion Specifications • Examples showing the effect of the minimum field • The minimum field width and precision are width and precision on the %s conversion: usually embedded in the format string. Result of Applying Result of Applying • Putting the * character where either number Conversion Conversion to Conversion to Specification "bogus""buzzword" would normallygo allows us to s pecify it as an %6s •bogus buzzword argument after the format string. %-6s bogus• buzzword • Calls of printf that ppproduce the same output: %.4s bogu buzz printf("%6.4d", i); %6.4s ••bogu ••buzz printf ("%*.4d" ,,);, 6, i); %-646.4s bogu•• buzz•• printf("%6.*d", 4, i); printf("%*.*d", 6, 4, i);

75 Copyright © 2008 W. W. Norton & Company. 77 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Examples of …printf Examples of …printf Conversion Specifications Conversion Specifications • A major advantage of * is that it allows us to use a •The %n conversion is used to find out how many macro to specify the width or precision: characters have been printed so far by a call of printf("%*d", WIDTH, i); …printf. • The width or ppprecision can even be computed • After the following call, the value of len will be during program execution: 3: pp(,rintf("%*d", ppgage__ width / num cols, i); printf("%d%n\n", 123, &len);

78 Copyright © 2008 W. W. Norton & Company. 80 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Examples of …printf The …scanf Functions Conversion Specifications •The %p conversion is used to print the value of a • fffscanf and scanf readda ta it ems f rom an pointer: input stream, using a format string to indicate the printf("%p", (void *) ptr); ltfthitlayout ofthe input. /* displays value of ptr */ • After the format string, any number of pointers— • The pointer is likely to be shown as an octal or each pointing to an object—follow as additional hexadecimal number. arguments. • Input items are converted (according to conversion sppg)ecifications in the format string) and stored in these objects.

79 Copyright © 2008 W. W. Norton & Company. 81 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output The …scanf Functions The …scanf Functions • scanf aldflways reads from stdin, whereas • The …scanf ftitfunctions return th thbfdte number ofdata fscanf reads from the stream indicated by its items that were read and assigned to objects. first argument : • They return EOF if an input failure occurs before scanf("%d%d", &i, &j); any data items can be read. /*df/* reads from s tdi*/tdin */ • Loops that test scanf’s return value are common. fscanf(fp, "%d%d", &i, &j); /* reads from fp */ • A loop that reads a series of integers one by one, • A call of scanf is equivalent to a call of stopping at the first sign of trouble: while (scanf(" %d" ,,&i) &i)== 1) { fffscanf with stdin as the fi rst argument . … }

82 Copyright © 2008 W. W. Norton & Company. 84 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output The …scanf Functions …scanf Format Strings • EthtthErrors that cause the …scanf ftittfunctions to return • CllCalls ofth e …scanf ftifunctions resembl blthfe those of prematurely: the …printf functions. – Input failure (no more input characters could be read) • However, the …scanf functions work differently. – Matching failure (the input characters didn’t match the • The format stringgp represents a p attern that a ftti)format string) …scanf function attempts to match as it reads • In C99, an input failure can also occur because of input. an encoding error. – If the input doesn’t match the format string, the function returns. – The input character that didn’t match is “pushed back” to be read in the future.

83 Copyright © 2008 W. W. Norton & Company. 85 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output …scanf Format Strings …scanf Format Strings • A …scanf forma t st ri ng may cont ai n th ree thi ngs: • White-space chtharacters. OhitOne or more white-space – Conversion specifications characters in a format string match zero or more – White-space characters white-space chtithittharacters in the input stream. – Non-white-space characters • Non-white-space characters. A non-white-space character other than % matches the same character in the input stream.

86 Copyright © 2008 W. W. Norton & Company. 88 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output …scanf Format Strings …scanf Format Strings • CiConversion specifi ifitications. CiConversion • The forma t s tr ing "ISBN %d-%d-%ld-%d" specifications in a …scanf format string resemble specifies that the input will consist of: those i n a …pritfintf fttiformat string. – thlhe letters ISBN • Most conversion specifications skip white-space – possibly some white-space characters characters at the beginning of an input item (the – an itinteger exceptions are %[, %c, and %n). –the - character – an itinteger ( possibl y preced ddbedby whit e-space cht)haracters) • Conversion specifications never skip trailing –the - character white-space characters, however. – a long integer (possibly preceded by white-space characters) –the - character – an integer (possibly preceded by white-space characters)

87 Copyright © 2008 W. W. Norton & Company. 89 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output …scanf Conversion Specifications …scanf Conversion Specifications Length • A …scanf conversiifitiitfion specification consists of Modifier Conversion Specifiers Meaning the character % followed by: hh† d, i, o, u, x, X, n signed char *, unsigned char * –* h d, i, o, u, x, X, nshthort itint *, unsidigned shthort itint * ld, i, o, u, x, X, n long int *, unsigned long int * – Maximum field width (ell) a, A, e, E, f, F, g, G double * – Length modifier c, s, or [ wchar_t * – Conversion specifier ll† d, i, o, u, x, X, n long long int *, •*(optional). Signifies assignment suppression: (ell-ell) unsigned long long int * j† d, i, o, u, x, X, n intmax_t *, uintmax_t * an input item is read but not assigned to an object. z† d, i, o, u, x, X, n size_t* – Items matched using * aren’t included in the count that t† d, i, o, u, x, X, n ptrdiff_t * …scanf returns. La, A, e, E, f, F, g, G long double * †C99 only

90 Copyright © 2008 W. W. Norton & Company. 92 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output …scanf Conversion Specifications …scanf Conversion Specifications • Max imum fie ld width (til)Liitth(optional). Limits the • CiConversion specifier. MtbMustbe one ofth e number of characters in an input item. characters in the following table. – White-space characters skipped at the beginning of a Conversion conversion don’t count. Specifier Meaning d Matches a decimal integg;er; the corresp onding arg ument • LhdifiLength modifier (i(optional) l)Idihh. Indicates that the is assumed to have type int *. object in which the input item will be stored has a i Matches an integer; the corresponding argument is assumed to have type int *. The integer is assumed to type th’lhat’s longer or sh orter th an normal . be in base 10 unless it begins with 0 (indicating octal) • The table on the next slide lists each length or with 0x or 0X (hexadecimal). o Matches an octal integer; the corresponding argument is modifier and the type indicated when it is assumed to have type unsigned int *. combined with a conversion specifier. u Matches a decimal integer; the corresponding argument idhis assumed to have type unsigned int *.

91 Copyright © 2008 W. W. Norton & Company. 93 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output …scanf Conversion Specifications …scanf Conversion Specifications Conversion Specifier Meaning • Numer ic da ta it ems can al ways b egi n with a si gn x, X Matches a hexadecimal integer; the corresponding (+ or -). argument is assumed to have type unsigned int *. •The o, u, x, and X specifiers convert the item to a†, A†, e, E, Matches a floating-point number; the corresponding f, F†, g, G argument is assumed to have type float *. unsigned form, however, so they’re not normally c Matches n characters, where n is the maximum field used to read negative numbers. width, or one character if no field width is specified. The corresppggonding argument is assumed to be a pointer to a character array (or a character object, if no field width is specified). Doesn’t add a null character at the end. s Matches a sequence of non-white-space characters, then adds a null character at the end. The corresponding argument is assumed to be a pointer to a character array. †C99 onl y

94 Copyright © 2008 W. W. Norton & Company. 96 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output …scanf Conversion Specifications …scanf Conversion Specifications Conversion • The [ specifier is a more complicated (and more Specifier Meaning flexible) version of the s specifier. [ Matches a nonempty sequence of characters from a scanset, then adds a null character at the end. The • A conversion specification using [ has the form %[set] corresponding argument is assumed to be a pointer to a or %[^set], where set can be any set of characters. character array. p MhMatches a po inter val lihfue in the form th at …printf • %[set] matches any sequence of characters in set (the would have written it. The corresponding argument is scanset). assumed to be a pointer to a void * object. • %[^set] matches any sequence of characters not in set. n The corresponding argument must point to an object of type int. Stores in this object the number of characters •Examples: read so far by this call of …scanf. No input is consumed and the return value of …scanf isn’t affected. %[abc] matches any string containing only a, b, and c. % Matches the character %. %[^abc] matches any string that doesn’t contain a, b, or c.

95 Copyright © 2008 W. W. Norton & Company. 97 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output C99 Changes to …scanf …scanf Conversion Specifications Conversion Specifications • MfthMany ofthe …scanf conversiifiion specifiers are • C99 changes to the conversion specifications for closely related to the numeric conversion scanf and fscanf: ftiifunctions in . – Additional length modifiers • These functions convert strings (like "-297") to – Additional conversion specifiers their equivalent numeric values (–297). – Ability to read infinity and NaN •The d specifier, for example, looks for an optional – Support for wide characters + or - sign, followed by decimal digits; this is the same form that the strtol function requires.

98 Copyright © 2008 W. W. Norton & Company. 100 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output …scanf Conversion Specifications scanf Examples • CdbtCorrespondence between …scanf conversion • The nextth t three t abl es cont ai n sampl e call s of specifiers and numeric conversion functions: scanf. Conversion • Characters printed in strikeout are consumed by Specifier Numeric Conversion Function the call. d strtol with 10 as the base i strtol with 0 as the base o strtoul with 8 as the base u strtoul with 10 as the base x, X strtoul with 16 as the base a, A, e, E, f, F, g, G strtod

99 Copyright © 2008 W. W. Norton & Company. 101 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output scanf Examples scanf Examples

• Exampl es th at combi ne conversi on specifi cati ons, whit e- • Examples that illustrate the i, [, and n conversion specifiers: space characters, and non-white-space characters: scanf Call Input Variables scanf Call Input Variables n = scanf(" %i%i%i" , &i, &j, &k); 12• 012• 0x12¤ n:3 n = scanf("%d%d", &i, &j); 12•,•34¤ n: 1 i: 12 i: 12 j: 10 j: unchanged k:18 n = scanf("%d,%d", &i, &j); 12•,•34¤ n: 1 n = scanf("%[0123456789]", str); 123abc¤ n: 1 i: 12 str: "123" j: unchanged n = scanf("%[0123456789]",st)tr);abc 123¤ n: 0 n = scanf("%d ,%d", &i, &j); 12•,•34¤ n: 2 str: unchanged i: 12 n = scanf("%[^0123456789]", str); abc123¤ n: 1 j: 34 str: "abc" n = scanf("%d, %d", &i, &j); 12•,•34¤ n: 1 n = scanf("%*d%d%n", &i, &j); 10•20•30¤ n: 1 i: 12 i: 20 j: unchanged j: 5

102 Copyright © 2008 W. W. Norton & Company. 104 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output

scanf Examples Detecting End-of-File and Error Conditions • ElhithfftfitExamples showing the effect of assignment suppressi on • If we as k a …scanf ftitfunction to read ddt and store n and specifying a field width: data items, we expect its return value to be n. scanf Call Input Variables n = scanf("%*d%d", &i); 12•34¤ n: 1 • If the return value is less than n, something went i: 34 wrong: n = scanf("%*s%s", str); My•Fair•Lady¤ n:1 str: "Fair" – End-of-file. The function encountered end-of-file n = scanf("%1d%2d%3d", 12345¤ n: 3 before matching the format string completely. &ijk)i, &j, &k); i: 1 – Read error. The function was unable to read characters j: 23 k: 45 from the stream. n = scanf("%2d%2s%2d", 123456¤ n: 3 – MhifilMatching failure. Adata item was in th e wrong f ormat. &i, str, &j); i: 12 str: "34" j: 56

103 Copyright © 2008 W. W. Norton & Company. 105 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output

Detecting End-of-File and Error Conditions Detecting End-of-File and Error Conditions • Every st ream h as t wo i ndi cat ors associ at ed with it: • The fffeof and ferror ftifunctions can b e usedt o an error indicator and an end-of-file indicator. test a stream’s indicators to determine why a prior • These indicators are cleared when the stream is operation on th e st ream f ail ed . opened. • The call feof(fp) returns a nonzero value if the • Encountering end-of-file sets the end-of-file end-of-file indicator is set for the stream indicator, and a read error sets the error indicator. associated with fp. – The error indicator is also set when a write error occurs • The call ferror(fp) returns a nonzero value if on an output stream. the error indicator is set. • A matching failure doesn’t change either indicator.

106 Copyright © 2008 W. W. Norton & Company. 108 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output

Detecting End-of-File and Error Conditions Detecting End-of-File and Error Conditions • OthOnce the error or end -of-file i ndi cat or i s set , it • When scanf retllturns a smaller-than-expectdted remains in that state until it’s explicitly cleared, value, feof and ferror can be used to perhbhaps by a ca llfthll ofthe clearerr ftifunction. dtdetermi ne th e reason. • clearerr clears both the end-of-file and error – If feof returns a nonzero value, the end of the input indicators: file h as b een reach ed . clearerr(fp); – If ferror returns a nonzero value, a read error /* clears eof and error idiindicators for fp */ occurred during input. • clearerr isn’t needed often, since some of the – If neither returns a nonzero value, a matching failure other library f uncti ons cl ear one or b othi h indi cators must have occurred. as a side effect. • The return value of scanf indicates how many data items were read before the problem occurred.

107 Copyright © 2008 W. W. Norton & Company. 109 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Detecting End-of-File and Error Conditions Character I/O • The fiditfind_int ftiifunction is an exampl lthte that • The next group of library f uncti ons can read and shows how feof and ferror might be used. write single characters. • find_int searches a file for a line that begins • These functions work equally well with text with an integer: streams and binary streams. n = find_int("foo"); • The functions treat characters as values of type • find_ int returns the value of the integer that it int, not char. finds or an error code: • One reason is that the input functions indicate an –1 File can’t be opened end-of-file (()or error) condition b y returnin gEOF, –2 Read error which is a negative integer constant. –3 No line begggins with an integer

110 Copyright © 2008 W. W. Norton & Company. 112 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output in ttfi find _i nt( cons t c har *filename ) { Output Functions FILE *fp = fopen(filename, "r"); int n; •puthtchar writes one ch aract er t o th e stdou t if (fp == NULL) return -1; /* can't open file */ stream:

while (fscanf(fp, "%d", &n) != 1) { putchar(ch); /* writes ch to stdout */ if (ferror(fp)) { fclose(fp); • fputc and putc write a character to an arbitrary return -2; /* read error */ } stream: if (feof(fp)) { fputc(ch, fp); /* writes ch to fp */ fclose(fp); return -3; /* integer not found */ putc(ch, fp); /* writes ch to fp */ } fscanf(fp, "%*[^\n]"); /* skips rest of line */ • putc is usually implemented as a macro (as well } as a function), while fputc is implemented only fclose(fp); return n; as a function. }

111 Copyright © 2008 W. W. Norton & Company. 113 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Output Functions Input Functions •puthtchar itself is usually ll a macro: •getc illiltdis usually implemented as a macro ( (llas well #define putchar(c) putc((c), stdout) as a function), while fgetc is implemented only •Thddllhhe C standard allows the putc macro to evaluate as a ftifunction. the stream argument more than once, which fputc • getchar is normally a macro as well: i’isn’t permi idtted to d o. #define getchar() getc(stdin) • Programmers usually prefer putc, which gives a •Proggyprammers usuallyprefer getc over fgetc. faster program. • If a write error occurs, all three functions set the error indicator for the stream and return EOF. •Otherwise,,y they return the character that was written.

114 Copyright © 2008 W. W. Norton & Company. 116 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Input Functions Input Functions •gethtchar readhtfds a character from stdin: • The ftfgetc, getc, and gethtchar ftifunctions ch = getchar(); behave the same if a problem occurs. • fgetc and getc readhd a character f rom an arbi trary •At end-of-file, they set the stream’s end-of-file stream: indicator and return EOF. ch = fgetc(fp); • If a read error occurs, they set the stream’s error ch = getc(fp); indicator and return EOF. •All th ree f uncti ons treat th e ch aracter as an • To differentiate between the two situations, we unsigned char value (which is then converted to can call either feof or ferror. itint ttype b ef ore it’ s ret urned) . • As a result, they never return a negative value other than EOF.

115 Copyright © 2008 W. W. Norton & Company. 117 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Input Functions Input Functions • OfthtOne ofthe most common uses of ftfgetc, getc, • The numb er of ch aract ers th at can b e push edb d back and getchar is to read characters from a file. by consecutive calls of ungetc varies; only the • A typical while loop for that purpose: first call is guarant eedt d to succeed . while ((ch = getc(fp)) != EOF) { • Calling a file-positioning function (fseek, … fsetpos, or rewind) causes the pushed-back } characters to be lost. itint • Alwa ys store the retu rn v alu eeinan in an variable, • ungetc returns the character it was asked to push not a char variable. back. • Testing a char varibliable agai nst EOF may gihive the – It returns EOF if an attempt is made to push back EOF wrong result. or to push back more characters than allowed.

118 Copyright © 2008 W. W. Norton & Company. 120 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Input Functions Program: Copying a File • The ungetc fti“hbk”hfunction “pushes back” a charact er • The fcopy.c program makffilkes a copy of a file. read from a stream and clears the stream’s end-of- • The names of the original file and the new file will file i ndi cat or. be specified on the command line when the • A loop that reads a series of digits, stopping at the program is executed. first nondigit: • An example that uses fcopy to copy the file while (isdigit(ch = getc(fp))) { f1.c to f2.c: … } fcopy f1.c f2.c ungetc(ch, fp); • fcopy will issue an error message if there aren’ t /* pushes back last character read */ exactly two file names on the command line or if either file can’t be opened.

119 Copyright © 2008 W. W. Norton & Company. 121 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output

if ((source_ fp = f open (argv [1], " r b")) == NULL) { Program: Copying a File fprintf(stderr, "Can't open %s\n", argv[1]); exit(EXIT_FAILURE); • UiUsing "b""rb" and "b""wb" as the fil e mod es enabl es } fcopy to copy both text and binary files. if ((dest_fp = fopen(argv[2], "wb")) == NULL) { fprintf(stderr, " Can' t open %s\n" , argv[2]); • If we used "r" and "w" instead, the program fclose(source_fp); exit(EXIT_FAILURE); wouldn’t necessarily be able to copy binary files. }

while ((ch = getc(source_fp)) != EOF) putc(ch, dest_fp);

fclose(source_fp); fclose(dest_fp); return 0; }

122 Copyright © 2008 W. W. Norton & Company. 124 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output fcopy.c Line I/O /* Copies a file */ • Library f uncti ons i n th e next group are abl e t o #include #include read and write lines. int main(int argc, char *argv[]) • These functions are used mostly with text streams, { although it’s legal to use them with binary streams FILE *source _ fp, *dest_ fp; int ch; as well.

if (argc != 3) { fprintf(stderr, "usage: fcopy source dest\n"); exit(EXIT_FAILURE); }

123 Copyright © 2008 W. W. Norton & Company. 125 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Output Functions Input Functions • The puts ftiittifhttfunction writes a string of characters to • The gets ftidlifitffunction reads a line ofinputfrom stdout: stdin: puts("Hi, there!"); /* writes to stdout */ gets(str); /* reads a line from stdin */ • After it writes the characters in the string, puts • gets reads characters one by one, storing them in always adds a new-line character. the array pointed to by str, until it reads a new- line character (which it discards). • fgets is a more general version of gets that can read from any stream. • fgets is also safer than gets, since it limits the number of characters that it will store.

126 Copyright © 2008 W. W. Norton & Company. 128 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Output Functions Input Functions • ftfputs ilifis a more general version of puts. • AllfA call of ftfgets that read s a li ne i nt o a ch aract er • Its second argument indicates the stream to which array named str: the output should be written: fgets(str, sizeof(str), fp); fputs("Hi, there!", fp); /* writes to fp */ • fgets will read characters until it reaches the • Unlike puts, the fputs function doesn’t write a first new-line character or sizeof(str) –1 new-line character unless one is present in the characters have been read. string. • If it reads the new-line character, fgets stores it • Both functions return EOF if a write error occurs; along with the other characters. otherwise, they return a nonnegative number.

127 Copyright © 2008 W. W. Norton & Company. 129 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Input Functions Block I/O • BthBoth gets and ftfgets retllitifturn a null pointer if a • The fdfread and fitfwrite ftillfunctions allow a read error occurs or they reach the end of the input program to read and write large blocks of data in a stbftihttream before storing any characters. siltingle step. • Otherwise, both return their first argument, which • fread and fwrite are used primarily with points to the array in which the input was stored. binary streams, although—with care—it’s possible • Both functions store a null character at the end of to use them with text streams as well. the string.

130 Copyright © 2008 W. W. Norton & Company. 132 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Input Functions Block I/O • ftfgets shldbhould be usedi ditdfnstead of gets itin most • fitfwrite idis desig inedt o copy an arrayf from memory situations. to a stream. • gets is safe to use only when the string being • AillfArguments in a call of fwrite: read is guaranteed to fit into the array. – Address of array • When there’s no guarantee (and there usually – Size of each array element (in bytes) isn’t), it’s much safer to use fgets. – Number of elements to write – File poi nter • fgets will read from the standard input stream if • A call of fwrite that writes the entire contents of passed stdin as its third argument: the array a: fgets(str, sizeof(str), stdin); fwrite(a, sizeof(a[0]), sizeof(a) / sizeof(a[0]), fp);

131 Copyright © 2008 W. W. Norton & Company. 133 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Block I/O Block I/O • fitfwrite retthbflttllturns the number of elements actually • fitfwrite iitfthtdtis convenientfor a program that needs to written. store data in a file before terminating. • This number will be less than the third argument if • Later, the program (or another program) can use a write error occurs. fread to read the data back into memory. • The data doesn’t need to be in array form. • A call of fwrite that writes a structure variable s to a file: fwrite(&s, sizeof(s), 1, fp);

134 Copyright © 2008 W. W. Norton & Company. 136 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Block I/O File Positioning • fdfread will readth d the el ement s of an arrayf from a • Every st ream h as an associ itdated file positi on. stream. • When a file is opened, the file position is set at the • AllfA call of fread thdhhat reads the contents of ffili a file into beginning of the file. the array a: – In “append” mode, the initial file position may be at the n = fread(a, sizeof(a[0]), beginning or end, depending on the implementation. sizeof(a) / sizeof(a[0]), fp); • When a read or write operation is performed, the • fdfread’s ret urn val ue i ndi cat es th e act ual numb er of file position advances automatically, providing elements read. sequential access to data. • This number should equal the third argument unless the end of the input file was reached or a read error occurred.

135 Copyright © 2008 W. W. Norton & Company. 137 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output File Positioning File Positioning • Although sequenti al access i s fi ne f or many • UiUsing fkfseek ttthbiiffilto move to the beginning of a file: applications, some programs need the ability to fseek(fp, 0L, SEEK_SET); jump around withi n a fil e. • Using fseek to move to the end of a file: • If a file contains a series of records, we might fseek(fp, 0L, SEEK_END); want to jump directly to a particular record. • Using fseek to move back 10 bytes: • provides five functions that allow a fseek((p,fp, -10L, SEEK_ CUR); program to determine the current file position or to • If an error occurs (the requested position doesn’t change it. exist, for example), fseek returns a nonzero value.

138 Copyright © 2008 W. W. Norton & Company. 140 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output File Positioning File Positioning • The fkfseek func tion ch anges th e fil e positi on • The fil e-positioni ng f uncti ons are b est used with associated with the first argument (a file pointer). binary streams. • The third argument is one of three macros: • C doesn’t prohibit programs from using them with SEEK_SET Beginning of file text streams, but certain restrictions apply. SEEK_CUR Current file position • For text streams, fseek can be used only to move SEEK_END End of file to the beggginning or end of a text stream or to • The second argument, which has type long int, return to a place that was visited previously. is a (possibl y ne gative ) b yte count. • For binaryy, streams, fseek isn’t required to support calls in which the third argument is SEEK_ END.

139 Copyright © 2008 W. W. Norton & Company. 141 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output File Positioning File Positioning • The fte ll func tion ret urns th e current file • The rewidind func tion set s th e fil e positi on atth t the position as a long integer. beginning. • The value returned by ftell may be saved and • The call rewind(fp) is nearly equivalent to later supplied to a call of fseek: fseek(fp, 0L, SEEK_SET). long file_pos; – The difference? rewind doesn’t return a value but … does clear the error indicator for fp. file_ pos = ftell(fp); /* saves current position */ … fseek(fp, file_pos, SEEK_SET); /* returns to old position */

142 Copyright © 2008 W. W. Norton & Company. 144 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output File Positioning File Positioning • If fp is a bi nary st ream, th e call fte ll(fp) • fkfseek and fte ll are limit edt d to fil es wh ose returns the current file position as a byte count, positions can be stored in a long integer. where zero represen ts th e b egi nni ng ofth f the fil e. • For working with very large files, C provides two • If fp is a text stream, ftell(fp) isn’t additional functions: fgetpos and fsetpos. necessarily a byte count. • These functions can handle large files because • As a result, it’s best not to perform arithmetic on they use values of type fpos_t to represent file values returned by ftell. positions. –An fpos_ t value isn’t necessarily an integer; it could be a structure, for instance.

143 Copyright © 2008 W. W. Norton & Company. 145 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output File Positioning Program: Modifying a File of Part Records • The call ftfgetpos (fp, &file_pos ) stthtores the • AtiActions perf ormedb y th e ilinvclear.c file position associated with fp in the file_pos program: varibliable. – Opens a binary file containing part structures. • The call fsetpos(fp, &file_pos) sets the – Reads the structures into an array. file position for fp to be the value stored in – Sets the on_hand member of each structure to 0. file_pos. – Writes the structures back to the file. • If a call of fgetpos or fsetpos fails, it stores • The program opens the file in "rb+" mode, an error code in errno. allowing both reading and writing. • Both functions return zero when they succeed and a nonzero value when they fail.

146 Copyright © 2008 W. W. Norton & Company. 148 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output File Positioning invclear.c /* Modifies a file of part records by setting the quantity • AlthtAn example that uses ftfgetpos and ftfsetpos to on hand to zero for all records */

save a file position and return to it later: #include fpos_t file_pos; #inc lu de … #define NAME_LEN 25 fgetpos(fp, &file_ pos); #define MAX_ PARTS 100 /* saves current position */ … struct part { int number; fsetpos(fp, &file_pos); char name[NAME_LEN+1]; /* returns to old position */ int on_hand; } inventory[MAX_ PARTS];

int num_parts;

147 Copyright © 2008 W. W. Norton & Company. 149 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output itint ma i(in(vo id) { FILE *fp; String I/O int i; • Three si mil ar f uncti ons ( vspritfintf, if ((fp = fopen("inventory.dat", "rb+")) == NULL) { fprintf(stderr, "Can't open inventory file\n"); vsnprintf, and vsscanf) also belong to exi(it(EXIT_FAILURE ); . } • These functions rely on the va_list type, which num_parts = fread (inventor y, sizeof (struct part ), MAX_PARTS, fp); is declared in , so they are

for (i = 0; i < num_parts; i++) discussed in Chapter 26. inventory[i].on_hand = 0;

rewind(fp); fwrite(inventory, sizeof(struct part), num_ parts, fp); fclose(fp);

return 0; }

150 Copyright © 2008 W. W. Norton & Company. 152 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output String I/O Output Functions • The f uncti ons d escrib edi d in thi s secti on can read • The spritfintf ftiitttitfunction writes outputinto a and write data using a string as though it were a character array (pointed to by its first argument) stream. itdfinstead of a st ream. • sprintf and snprintf write characters into a • A call that writes "9/20/2010" into date: string. sprintf(date, "%d/%d/%d", 9, 20, 2010); • sscanf reads characters from a string. • sprintf adds a null character at the end of the string. • It returns the number of characters stored (not counting the null character).

151 Copyright © 2008 W. W. Norton & Company. 153 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Output Functions Output Functions • spritfintf can be usedt d to f ormatd t dat a, with the • snpritfintf retthbfhtthtturns the number of characters that result saved in a string until it’s time to produce would have been written (not including the null outttput. cht)hdthbharacter)hadthere been no l lthtitiength restriction. • sprintf is also convenient for converting • If an encoding error occurs, snprintf returns a numbers to character form. negative number. • To see if snprintf had room to write all the requested characters, we can test whether its return value was nonnegative and less than n.

154 Copyright © 2008 W. W. Norton & Company. 156 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Chapter 22: Input/Output Output Functions Input Functions • The snpritfintf func tion ( new i n C99) is th e same • The sscanf ftiiiiltfunction is similar to scanf and as sprintf, except for an additional second fscanf. parametdter named n. • sscanf reads from a string (pointed to by its first •No more than n – 1 characters will be written to argument) instead of reading from a stream. the string, not counting the terminating null • sscanf’s second argument is a format string character, which is always written unless n is zero. identical to that used by scanf and fscanf. •Example: snprintf(name, 13, "%s, %s", "Einstein", "Albert"); The string "Einstein, Al" is written into name.

155 Copyright © 2008 W. W. Norton & Company. 157 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved. Chapter 22: Input/Output Chapter 22: Input/Output Input Functions Input Functions • sscanf ihis hand dfy for ext racti tidtfng data from a st tiring • Like th e scanf and fffscanf ftifunctions, sscanf that was read by another input function. returns the number of data items successfully read • An example that uses fgets to obtain a line of andtd stored . input, then passes the line to sscanf for further • sscanf returns EOF if it reaches the end of the processing: string (marked by a null character) before finding fgets(str, sizeof(str), stdin); the first item. /* reads a line of input */ sscanf(str, "%d%d", &i, &j); /* extracts two integers */

158 Copyright © 2008 W. W. Norton & Company. 160 Copyright © 2008 W. W. Norton & Company. All rights reserved. All rights reserved.

Chapter 22: Input/Output Input Functions • One advantage of using sscanf is that we can examine an input line as many times as needed. • This makes it easier to recognize alternate input forms and to recover from errors. • Consider the problem of reading a date that’ s written either in the form month/day/year or month-day-year: if (((,sscanf(str, "%d /%d //,%d", &month, &day, &yy)ear) == 3) printf("Month: %d, day: %d, year: %d\n", month, day, year); else if (sscanf(str, "%d -%d -%d", &month, &day, &year) == 3) printf("Month: %d, day: %d, year: %d\n", month, day, year); else printf("Date not in the proper form\n");

159 Copyright © 2008 W. W. Norton & Company. All rights reserved.