Chapter 2
Introduction to C Programming
Introduction to C Programming
Outline
|
2.1
|
Introduction
|
2.4
|
Arithmetic in C
|
2.2
|
A Simple C Program: Printing a Line
|
2.5
|
Decision Making: Equality and
|
of Text
|
Relational Operators
|
||
2.3
|
Another Simple C Program: Adding
|
2.6
|
Secure C Programming
|
Two Integers
|
|||
The C language facilitates a structured and
disciplined approach to computer-program design. In this chapter we introduce C
programming and present several examples that illustrate many important
features of C. In Chapters 3 and 4 we present an introduction to structured
programming in C. We then use the structured approach throughout the re-mainder
of the text.
We begin by considering a simple C program. Our
first example prints a line of text. The program and its screen output are
shown in Fig. 2.1.
1 // Fig. 2.1:
fig02_01.c
2 // A
first program in C.
3 #include
<stdio.h>
4
5 // function
main begins program execution
6 int
main( void )
7
{
8 printf( "Welcome to C!\n" );
9 } //
end function main
Welcome
to C!
Fig. 2.1 | A first program in C.
Comments
This program illustrates several important C features. Lines 1 and 2
// Fig. 2.1: fig02_01.c
// A first program in C
begin with //, indicating that these two lines are comments. Comments do not
cause the computer to perform any action when the program is run. Comments are ignored by the C compiler and do not cause any machine-language object
code to be generated. The pre-ceding comment simply describes the figure
number, file name and purpose of the pro-gram.
You can also use /*…*/ multi-line comments in which
everything from /* on the first line to */ at the end of the last line is a comment. We prefer // comments because they’re shorter and they eliminate common programming
errors that occur with /*…*/ comments, especially when the closing */ is omitted.
21
|
#include
Preprocessor Directive
Line 3
#include <stdio.h>
is a directive to the C
preprocessor. Lines beginning with # are processed by the prepro-cessor before
compilation. Line 3 tells the preprocessor to include the contents of the stan-dard input/output header (<stdio.h>) in the
program. This header contains information
used by the compiler when compiling calls to standard input/output library
functions such as printf (line 8). We explain the
contents of headers in more detail in Chapter 5.
Blank Lines and White Space
Line 4 is simply a blank line. You use blank lines,
space characters and tab characters (i.e., “tabs”) to make programs easier to
read. Together, these characters are known as white space. White-space
characters are normally ignored by the compiler.
The main Function
Line 6
int
main( void )
is a part of every C program. The parentheses after
main indicate that main is a function.
C programs contain one or more functions, one of which must be main. Every
program in C begins executing at the function main. Functions can return
information. The keyword int to the left of
main indicates that main “returns” an integer (whole-number) value. We’ll explain what this means when we demonstrate how to create your own
functions in Chapter 5. For now, simply include the keyword int to the left of main in each of your programs.
Functions also can receive
information when they’re called upon to execute. The void
in parentheses here means that
main does not receive any information. In
Chapter 14, we’ll show an example of main receiving information.
Good
Programming Practice 2.1
Every function should be preceded by a comment
describing the purpose of the function.
A left brace, {, begins the body of every
function (line 7). A corresponding right
brace ends each function (line 9). This pair of braces and the portion of
the program between the braces is called a block.
The block is an important program unit in C.
An Output Statement
Line 8
printf(
"Welcome
to C!\n" );
instructs the computer to perform an action, namely to print on the screen the string of characters marked by the quotation marks. A string is
sometimes called a character string,
a message or a literal. The entire line, including the printf function (the “f” stands for “formatted”), its argument within the parentheses and the
semicolon (;), is called a state-ment.
Every statement must end with a semicolon (also known as the statement termina-tor). When the
preceding printf statement is executed, it prints the message Welcome to C! on the
screen. The characters normally print exactly as they appear between the double quotes in the printf statement.
Escape Sequences
Notice that the characters \n were not printed on the screen. The backslash (\) is called an escape character.
It indicates that printf is supposed to do something out of the ordinary. When encountering a backslash in a string, the compiler looks
ahead at the next character and combines it with the backslash to form an escape sequence. The escape sequence \n means newline. When a newline appears in the
string output by a printf, the
newline causes the cursor to position to the beginning of the next line on the
screen. Some com-mon escape sequences are listed in Fig. 2.2.
Escape sequence
|
Description
|
\n
|
Newline.
Position the cursor at the beginning of the next line.
|
\t
|
Horizontal
tab. Move the cursor to the next tab stop.
|
\a
|
Alert.
Produces a sound or visible alert without changing the current
|
cursor
position.
|
|
\\
|
Backslash.
Insert a backslash character in a string.
|
\"
|
Double
quote. Insert a double-quote character in a string.
|
Fig. 2.2 | Some common escape sequences .
Because the backslash has special
meaning in a string, i.e., the compiler recognizes it as an escape character,
we use a double backslash (\\) to place a single backslash in a string. Printing
a double quote also presents a problem because double quotes mark the
bound-aries of a string—such quotes are not printed. By using the escape
sequence \" in a
string to be output by printf, we
indicate that printf should
display a double quote. The right brace, }, (line 9) indicates that the end of main has been reached.
Good
Programming Practice 2.2
Add a comment to the line
containing the right brace, }, that closes every function,
in-cluding main.
We said that printf causes the computer to perform an action.
As any program executes, it performs a variety of actions and makes decisions. Section 2.5 discusses
deci-sion making. Chapter 3 discusses this action/decision
model of programming in depth.
The Linker and Executables
Standard library functions like printf and scanf are not part of the C programming lan-guage. For example, the compiler cannot find a spelling error in printf or scanf. When the compiler compiles a printf statement, it merely provides space in the object program for a “call”
to the library function. But the compiler does not know where the library func-tions are—the linker does. When the linker runs, it locates the library functions
and inserts the proper calls to these library functions in the object program.
Now the object program is complete and ready to be executed. For this reason,
the linked program is called an ex-ecutable.
If the function name is misspelled, the linker will spot the error, because it will not be able to match the name in the C program with the name of
any known function in the libraries.
23
|
Good
Programming Practice 2.3
Indent
the entire body of each function one level of indentation (we recommend three
spaces) within the braces that define the body of the function. This
indentation emphasizes the functional structure of programs and helps make
programs easier to read.
Good
Programming Practice 2.4
Set a
convention for the size of indent you prefer and then uniformly apply that
conven-tion. The tab key may be used to create indents, but tab stops may vary.
Using Multiple printfs
The printf function
can print Welcome to C! several
different ways. For example, the pro-gram of Fig. 2.3 produces the same output
as the program of Fig. 2.1. This works because each printf resumes printing where the previous printf stopped printing. The first printf (line 8) prints Welcome followed by a space, and the second
printf (line 9) begins printing on the same
line immediately following the space.
1 // Fig. 2.3:
fig02_03.c
2 //
Printing on one line with two printf statements. 3 #include <stdio.h>
4
5 // function
main begins program execution
6 int
main( void )
7
{
8 printf( "Welcome
" );
9 printf( "to C!\n" );
10 } //
end function main
Welcome to C!
Fig. 2.3 | Printing on one line with two printf statements.
One printf can print several lines by
using additional newline characters as in Fig. 2.4. Each time the \n (newline) escape sequence is encountered, output continues at the
beginning of the next line.
1 // Fig. 2.4:
fig02_04.c
2 // Printing
multiple lines with a single printf.
3 #include
<stdio.h>
4
5 // function main
begins program execution
6 int
main( void )
7
{
8 printf( "Welcome \nto
\nC!\n" );
9
} // end function main
Welcome
to
C!
Fig. 2.4 | Printing multiple lines with a single printf.
Our next program uses the Standard Library function
scanf to obtain two integers typed by a user at the keyboard, computes the
sum of these values and prints the result using printf. The program and sample output are shown in Fig.
2.5. [In the input/output dia-log of Fig. 2.5, we emphasize the numbers entered
by the user in bold.]
1 // Fig. 2.5:
fig02_05.c
2 // Addition
program.
3 #include
<stdio.h>
4
5 // function
main begins program execution
6 int
main( void )
7
{
8
|
int
integer1; // first
number
|
to be entered
by user
|
|||
9
|
int
|
integer2; // second
|
number to
|
be entered by user
|
|
10
|
int
|
sum;
// variable in
|
which
|
sum
|
will be stored
|
11
|
12
printf( "Enter first integer\n" ); // prompt
13
scanf( "%d", &integer1 );
// read an integer
14
15
printf( "Enter second integer\n" ); // prompt
16
scanf( "%d", &integer2 );
// read an integer
17
18
sum = integer1 + integer2; // assign total to sum
19
20
printf( "Sum is %d\n", sum ); // print sum
21
} // end function main
Enter first integer
45
Enter
second integer
72
Sum
is 117
Fig. 2.5 | Addition program.
The
comment in line 2 states the purpose of the program. As we stated earlier,
every program begins execution with main. The left brace { (line 7) marks the beginning of the body of main, and the corresponding right brace } (line 21) marks the end of main.
Variables and Variable Definitions
Lines 8–10
int integer1; // first
number to be entered by user int integer2; // second
number to be entered by user int sum; //
variable in which sum will be stored
are definitions. The names integer1, integer2 and sum are the names of variables—lo-cations in memory where values can be stored for use
by a program. These definitions specify that variables integer1, integer2 and sum are of type int, which means that they’ll hold integer values, i.e., whole numbers
such as 7, –11, 0, 31914 and the like.
25
|
All variables must be defined
with a name and a data type before
they can be used in a program. For readers using the Microsoft Visual C++
compiler, note that we’re placing our variable definitions immediately after
the left brace that begins the body of main. The C standard allows you to place each variable
definition anywhere in main before that vari-able’s first use in the code.
Some compilers, such as GNU gcc, have
implemented this capability. We’ll address this issue in more depth in later
chapters.
The preceding definitions could have been combined
into a single definition state-ment as follows:
int
integer1,
integer2, sum;
but that would have made it difficult to describe the variables with
corresponding com-ments as we did in lines 8–10.
Identifiers and Case Sensitivity
A variable name in C is any valid identifier.
An identifier is a series of characters consisting of letters, digits and
underscores ( _) that does not begin with a digit. C is case
sensitive— uppercase and lowercase letters are different in C, so a1 and A1 are different identifiers.
Error-Prevention
Tip 2.1
Avoid
starting identifiers with the underscore character (_) to prevent conflicts with com-piler-generated identifiers and standard
library identifiers.
Good
Programming Practice 2.5
The first
letter of an identifier used as a simple variable name should be a lowercase
letter. Later in the text we’ll assign special significance to identifiers that
use all capital letters.
Good
Programming Practice 2.6
Multiple-word
variable names can help make a program more readable. Separate the words with
underscores as in total_commissions, or, if you run the words
together, begin each word after the first with a capital letter as in totalCommissions. The latter style is preferred.
Syntax Errors
We discussed what syntax errors are in Chapter 1.
Recall that the Microsoft Visual C++ compiler requires variable definitions to
be placed after the left brace of a
function and be-fore any executable
statements. Therefore, in the program in Fig. 2.5, inserting the defini-tion of
integer1 after
the first printf would
cause a syntax error in Visual C++.
Common
Programming Error 2.1
Placing variable definitions
among executable statements causes syntax errors in the Mi-crosoft Visual C++
Compiler.
Prompting Messages
Line 12
printf(
"Enter
first integer\n" ); // prompt
displays
the literal "Enter first integer" and positions the cursor to the beginning of the next line. This
message is called a prompt because
it tells the user to take a specific action.
The scanf Function
and Formatted Inputs
The next
statement
scanf(
"%d",
&integer1 ); // read an integer
uses scanf (the “f” stands for “formatted”) to obtain a value from
the user. The function reads from the standard
input, which is usually the keyboard. This scanf has two argu-ments, "%d" and &integer1. The first, the format control string, indicates the type of data that should be entered by the user. The %d conversion specifier indicates that the
data should be an integer (the letter d stands for “decimal integer”). The % in this context is treated by scanf (and printf as we’ll see) as a special character that begins a
conversion specifier. The second argument of scanf begins with an ampersand (&)—called the ad-dress
operator—followed by the variable name. The &, when
combined with the variable name,
tells scanf the location (or address) in memory at which the
variable integer1 is
stored. The computer then stores the value that the user enters for integer1 at that loca-tion. The use of ampersand (&) is often confusing to novice programmers or to
people who have programmed in other languages that do not require this
notation. For now, just re-member to precede each variable in every call to scanf with an ampersand. Some excep-tions to this rule
are discussed in Chapters 6 and 7. The use of the ampersand will become clear
after we study pointers in Chapter 7.
Good
Programming Practice 2.7
Place a space after each comma (,) to make programs more readable.
When the computer executes the preceding scanf, it waits for the user to enter a value for variable integer1. The user responds by typing an integer, then pressing the Enter
key to send the number to the
computer. The computer then assigns this number, or value, to the variable integer1. Any subsequent references to integer1 in this program will use this same value. Functions printf and scanf facilitate interaction between
the user and the computer. Because this interaction resembles a dialogue, it’s
often called interactive com-puting.
Line 15
printf(
"Enter
second integer\n" ); // prompt
displays the message Enter second integer on the
screen, then positions the cursor to the beginning of the next line. This printf also prompts the user to take action.
Line 16
scanf(
"%d",
&integer2 ); // read an integer
obtains a value for variable integer2 from the
user.
Assignment Statement
The assignment statement in line 18
sum
= integer1 + integer2; // assign total to sum
calculates the total of variables integer1 and integer2 and assigns the result to variable sum using the assignment operator =. The statement is read as, “sum gets the value of integer1 + integer2.” Most
calculations are performed in assignments. The = operator
27
|
and the + operator are called binary operators because each has two operands.
The + oper-ator’s two operands are integer1 and integer2. The = operator’s two operands are sum and the value of the expression integer1 + integer2.
Good
Programming Practice 2.8
Place spaces on either side of a
binary operator for readability.
Printing with a Format Control
String
Line 20
printf( "Sum is %d\n", sum ); // print sum
calls function printf to print the literal Sum
is followed by the numerical value
of variable sum on the screen. This
printf has two arguments,
"Sum is %d\n" and sum. The first ar-gument is the format control string. It contains some
literal characters to be displayed, and it contains the conversion specifier %d indicating that an integer will be printed. The sec-ond argument
specifies the value to be printed. Notice that the conversion specifier for an
integer is the same in both printf and scanf—this is the case for most C data types.
Calculations in printf Statements
Calculations can also be performed inside printf statements. We could have combined the previous two statements into the
statement
printf( "Sum is %d\n",
integer1 + integer2 );
The right
brace, }, at line 21 indicates that the
end of function main has been reached.
Common
Programming Error 2.2
Forgetting
to precede a variable in a scanf statement with an ampersand when
that vari-able should, in fact, be preceded by an ampersand results in an
execution-time error. On many systems, this causes a “segmentation fault” or “access
violation.” Such an error occurs when a user’s program attempts to access a
part of the computer’s memory to which it does not have access privileges. The
precise cause of this error will be explained in Chapter 7.
Common
Programming Error 2.3
Preceding
a variable included in a printf statement with an ampersand
when, in fact, that variable should not be preceded by an ampersand.
Most C programs perform calculations using the C arithmetic operators (Fig. 2.6). The asterisk (*) indicates multiplication and the percent sign (%) denotes the remainder opera-tor,
which is introduced below. In algebra, to multiply a times b, we simply
place these single-letter variable
names side by side, as in ab. In C,
however, if we were to do this, ab would be interpreted as a
single, two-letter name (or identifier). Therefore, multiplication must be
explicitly denoted by using the * operator, as in a *
b. The arithmetic operators are all binary operators. For example, the
expression 3 + 7 contains the binary operator + and the operands 3 and 7.
Chapter 2
|
Introduction
to C Programming
|
||||||
C operation
|
Arithmetic operator
|
Algebraic expression
|
C expression
|
||||
Addition
|
+
|
f + 7
|
f + 7
|
||||
Subtraction
|
–
|
p – c
|
p - c
|
||||
Multiplication
|
*
|
bm
|
x
|
b * m
|
|||
Division
|
/
|
x / y or
|
or x ÷ y
|
||||
x
/ y
|
|||||||
-
|
|||||||
Remainder
|
%
|
r mod s
|
y
|
||||
r
% s
|
|||||||
Fig. 2.6 | Arithmetic operators.
Integer Division and the
Remainder Operator
Integer division yields an integer result. For example, the expression 7 / 4 evaluates to 1 and the expression 17 / 5 evaluates
to 3. C provides the remainder
operator, %, which yields the remainder
after integer division. The remainder operator is an integer operator that can
be used only with integer operands. The expression x %
y yields the remainder af-ter x is divided by y. Thus, 7 %
4 yields 3 and 17 % 5 yields 2. We’ll discuss many interesting applications of the remainder operator.
Common
Programming Error 2.4
An
attempt to divide by zero is normally undefined on computer systems and
generally re-sults in a fatal error, i.e., an error that causes the program to terminate immediately
with-out having successfully performed its job. Nonfatal errors allow programs to run to completion, often
producing incorrect results.
Arithmetic Expressions in
Straight-Line Form
Arithmetic expressions in C must be written in straight-line form to facilitate
entering programs into the computer. Thus, expressions such as “a divided by b” must be written as a/b so that all operators and operands appear in a
straight line. The algebraic notation
a
--
b
is generally not acceptable to compilers, although some special-purpose
software packages do support more natural notation for complex mathematical
expressions.
Parentheses for Grouping
Subexpressions
Parentheses are used in C expressions in the same
manner as in algebraic expressions. For example, to multiply a times the quantity b + c we write a * ( b + c ).
Rules of Operator Precedence
C applies the operators in arithmetic expressions in a precise sequence
determined by the following rules of
operator precedence, which are generally the same as those in algebra:
1.
Operators in expressions
contained within pairs of parentheses are evaluated first. Parentheses are said
to be at the “highest level of precedence.” In cases of nested, or embedded, parentheses, such as
( ( a + b ) + c )
the operators in the innermost pair of parentheses are
applied first.
29
|
2.
Multiplication, division and
remainder operations are applied next. If an ex-pression contains several
multiplication, division and remainder operations, eval-uation proceeds from
left to right. Multiplication, division and remainder are said to be on the
same level of precedence.
3.
Addition and subtraction
operations are evaluated next. If an expression contains several addition and
subtraction operations, evaluation proceeds from left to right. Addition and
subtraction also have the same level of precedence, which is lower than the
precedence of the multiplication, division and remainder operations.
4.
The assignment operator (=) is evaluated last.
The rules of operator precedence
specify the order C uses to evaluate expressions.1 When we
say evaluation proceeds from left to right, we’re referring to the associativity of the operators. We’ll
see that some operators associate from right to left. Figure 2.7 sum-marizes
these rules of operator precedence for the operators we’ve seen so far.
Operator(s)
|
Operation(s)
|
Order of evaluation (precedence)
|
( )
|
Parentheses
|
Evaluated
first. If the parentheses are nested, the expres-
|
sion in
the innermost pair is evaluated
first. If there are
|
||
several pairs of parentheses “on the same level”
(i.e., not
|
||
nested),
they’re evaluated left to right.
|
||
*
|
Multiplication
|
Evaluated
second. If there are several, they’re evaluated
|
/
|
Division
|
left to
right.
|
%
|
Remainder
|
|
+
|
Addition
|
Evaluated third. If there are several, they’re evaluated
left
|
-
|
Subtraction
|
to
right.
|
=
|
Assignment
|
Evaluated
last.
|
Fig. 2.7 | Precedence of arithmetic operators.
Sample Algebraic and C Expressions
Now let’s consider several expressions in light of the rules of operator
precedence. Each example lists an algebraic expression and its C equivalent.
The following expression calcu-lates the arithmetic mean (average) of five
terms.
a + b + c + d +
e
Algebra: m =
-------------------------------------
5
C:
m = ( a + b + c + d + e ) / 5;
The parentheses are required to group the additions because division has
higher prece-dence than addition. The entire quantity ( a
+ b + c + d + e ) should be divided by 5. If the parentheses are erroneously omitted, we obtain a +
b + c + d + e / 5, which evaluates incorrectly as
e a + b +
c + d + -- 5
1.
We use simple examples to explain
the order of evaluation of expressions. Subtle issues occur in more complex
expressions that you’ll encounter later in the book. We’ll discuss these issues
as they arise.
The
following expression is the equation of a straight line:
Algebra: y = mx +
b
C:
y = m * x + b;
No parentheses are required. The multiplication is evaluated first
because multiplication has a higher precedence than addition.
The following expression contains remainder (%), multiplication, division, addition, subtraction and assignment
operations:
Algebra:
|
z = pr
%q + w/x – y
|
|||||
C:
|
z =
p * r
% q +
w / x
- y;
|
|||||
6
|
1
|
2
|
4
|
3
|
5
|
|
The circled numbers indicate the order in which C evaluates the
operators. The multipli-cation, remainder and division are evaluated first in
left-to-right order (i.e., they associate from left to right) because they have
higher precedence than addition and subtraction. The addition and subtraction
are evaluated next. They’re also evaluated left to right. Finally, the result
is assigned to the variable z.
Not all expressions with several pairs of
parentheses contain nested parentheses. For example, the following expression
does not contain nested parentheses—instead,
the parentheses are said to be “on the same level.”
a * ( b + c ) + c * ( d + e )
Evaluation of a Second-Degree
Polynomial
To develop a better understanding of the rules of operator precedence,
let’s see how C eval-uates a second-degree polynomial.
y = a * x * x + b * x + c;
6 1 2 4 3 5
The circled numbers under the statement indicate the order in which C performs
the oper-ations. There’s no arithmetic operator for exponentiation in C, so we’ve
represented x2 as x * x. The C
Standard Library includes the pow (“power”)
function to perform expo-nentiation. Because of some subtle issues related to
the data types required by pow, we
defer a detailed explanation of pow until
Chapter 4.
Suppose variables a, b, c and x in the preceding second-degree
polynomial are initial-ized as follows: a = 2, b = 3, c = 7 and x = 5. Figure 2.8 illustrates the
order in which the operators are applied.
As in algebra, it’s acceptable to place unnecessary
parentheses in an expression to make the expression clearer. These are called redundant parentheses. For example, the
pre-ceding statement could be parenthesized as follows:
y =
( a * x * x ) + ( b * x ) + c;
Fig. 2.8 | Order in which a second-degree polynomial is evaluated.
Executable statements either perform actions (such
as calculations or input or output of data) or make decisions (we’ll soon see several examples of these). We might make
a deci-sion in a program, for example, to determine whether a person’s grade on
an exam is great-er than or equal to 60 and whether the program should print
the message “Congratulations! You passed.” This section introduces a simple
version of C’s if state-ment that allows a program
to make a decision based on the truth or falsity of a statement of fact called a condition. If the condition is true
(i.e., the condition is met), the statement in the body of the if statement is executed. If the condition is false (i.e., the condition isn’t met), the body statement isn’t
executed. Whether the body statement is executed or not, after the if statement completes, execution proceeds with the next statement after
the if
statement.
Conditions in if statements are formed by using the equality
operators and relational operators summarized in Fig. 2.9. The
relational operators all have the same level of prece-dence and they associate
left to right. The equality operators have a lower level of prece-dence than
the relational operators and they also associate left to right. [Note: In C, a condition may actually be any expression that generates a zero (false)
or nonzero (true) value.]
Common
Programming Error 2.5
Confusing
the equality operator == with the assignment operator. To
avoid this confusion, the equality operator should be read “double equals” and
the assignment operator should be read “gets” or “is assigned the value of.” As
you’ll see, confusing these operators may not cause an easy-to-recognize
compilation error, but may cause extremely subtle logic errors.
Chapter 2
Introduction to C Programming
|
|||||
C equality or
|
Example
|
||||
Algebraic equality or
|
relational
|
of C
|
|||
relational operator
|
operator
|
condition
|
Meaning of C condition
|
||
Equality operators
|
|||||
=
|
==
|
x == y
|
x is
equal to
y
|
||
≠
|
!=
|
x != y
|
x is not
equal to
y
|
||
Relational operators
|
|||||
>
|
>
|
x > y
|
x is
greater than
y
|
||
<
|
<
|
x < y
|
x is less
than y
|
||
≥
|
>=
|
x >= y
|
x is
greater than or equal to
y
|
||
≤
|
<=
|
x <= y
|
x is less
than or equal to
y
|
||
Fig. 2.9
| Equality and relational operators.
Figure
2.10 uses six if
statements to compare two numbers entered by the user. If the condition in any
of these if
statements is true, the printf
statement associated with that if executes. The program and three
sample execution outputs are shown in the figure.
1 // Fig. 2.10:
fig02_10.c
2
// Using if statements, relational
3 // operators,
and equality operators.
4 #include
<stdio.h>
5
6 // function
main begins program execution
7 int
main( void )
8
{
9 int num1; // first number to be read from user
10 int num2;
// second number to be read from user
11
12
printf( "Enter two integers, and I will tell you\n"
);
13
printf( "the relationships they satisfy: "
);
14
15 scanf( "%d%d", &num1,
&num2 ); // read two integers
16
17 if
(
num1 == num2 ) {
18
printf( "%d is equal to %d\n", num1, num2 );
19
} // end if
20
21 if
( num1
!= num2 ) {
22
printf( "%d is not equal to %d\n", num1,
num2 );
23
} // end if
24
25 if
( num1
< num2 ) {
26
printf( "%d is less than %d\n", num1, num2
);
27
} // end if
Fig. 2.10 | Using if statements, relational operators, and equality operators. (Part 1 of 2.)
33
|
28
29 if
( num1
> num2 ) {
30
printf( "%d is greater than %d\n", num1,
num2 );
31
} // end if
32
33 if
( num1
<= num2 ) {
34
printf( "%d is less than or equal to %d\n",
num1, num2 );
35
} // end if
36
37 if
( num1
>= num2 ) {
38
printf( "%d is greater than or equal to %d\n",
num1, num2 );
39
} // end if
40
} // end function main
Enter
two integers, and I will tell you the relationships they satisfy: 3 7
3 is
not equal to 7
3 is less than 7
3 is less than or equal to 7
Enter
two integers, and I will tell you the relationships they satisfy: 22 12 22 is not equal to 12
22
is greater than 12
22 is greater than or equal
to 12
Enter
two integers, and I will tell you the relationships they satisfy: 7 7
7 is equal to 7
7 is less than or equal to 7
7 is
greater than or equal to 7
Fig. 2.10 | Using if statements, relational operators, and equality operators. (Part 2 of 2.)
The program uses scanf (line 15) to input two numbers. Each conversion specifier has a
corresponding argument in which a value will be stored. The first %d converts a value to be stored in the variable num1, and the second %d converts a value to be stored in
the variable num2.
Good
Programming Practice 2.9
Although it’s allowed, there should be no more than
one statement per line in a program.
Common
Programming Error 2.6
Placing commas (when none are needed) between conversion specifiers in
the format con-trol string of a scanf statement.
Comparing
Numbers
The if statement in lines 17–19
if ( num1 == num2 ) {
printf(
"%d is
equal to %d\n", num1, num2 );
}
compares the values of variables num1 and num2 to test for equality. If the
values are equal, the statement in line 18 displays a line of text indicating
that the numbers are equal. If the conditions are true in one or more of the if statements starting in lines 21,
25, 29, 33 and 37, the corresponding body statement displays an appropriate
line of text. Indenting the body of each if statement and placing blank lines above and below each if statement enhances program readability.
Common
Programming Error 2.7
Placing a semicolon immediately
to the right of the right parenthesis after the condition in an if statement.
A left brace, {, begins the body of each if statement (e.g., line 17). A corresponding right brace, }, ends each if statement’s body (e.g., line
19). Any number of statements can be placed in the body of an if statement.2
Good
Programming Practice 2.10
A lengthy
statement may be spread over several lines. If a statement must be split across
lines, choose breaking points that make sense (such as after a comma in a
comma-separated list). If a statement is split across two or more lines, indent
all subsequent lines. It’s not correct to split identifiers.
Figure 2.11 lists from highest to
lowest the precedence of the operators introduced in this chapter. Operators
are shown top to bottom in decreasing order of precedence. The equals sign is
also an operator. All these operators, with the exception of the assignment
operator =, associate from left to right.
The assignment operator (=) associates from right to left.
Good
Programming Practice 2.11
Refer to
the operator precedence chart when writing expressions containing many
opera-tors. Confirm that the operators in the expression are applied in the
proper order. If you’re uncertain about the order of evaluation in a complex
expression, use parentheses to group expressions or break the statement into
several simpler statements. Be sure to observe that some of C’s operators such
as the assignment operator (=) associate from right to left rather than from
left to right.
Some of the words we’ve used in
the C programs in this chapter—in particular int and if—are keywords or reserved words of the language. Figure 2.12 contains
the C key-words. These words have special meaning to the C compiler, so you
must be careful not to use these as identifiers such as variable names.
2.
Using braces to delimit the body
of an if statement is optional when the body contains only one statement. Many
programmers consider it good practice to always use these braces. In Chapter 3,
we’ll explain the issues.
Fig. 2.12 | C’s keywords.
We mentioned The CERT C Secure
Coding Standard in the Preface and indicated that we would follow certain
guidelines that will help you avoid programming practices that open systems to
attacks.
One such guideline is to avoid using printf with a
single string argument. If you need to display a string that terminates with a newline, use the puts function, which displays its string
argument followed by a newline character. For example, in Fig. 2.1, line 8
printf(
"Welcome
to C!\n" );
should be written as:
puts( "Welcome to C!" );
We did not include \n in the
preceding string because puts adds it
automatically.
If you need to display a string without a terminating newline character,
use printf with two
arguments—a "%s" format
control string and the string to display. The %s con-version
specifier is for displaying a string. For example, in Fig. 2.3, line 8
printf(
"Welcome
" );
should be written as:
printf( "%s", "Welcome
" );
Although the printfs in this chapter as written are actually not insecure, these changes are responsible coding practices that
will eliminate certain security vulnerabilities as we get deeper into C—we’ll
explain the rationale later in the book. From this point forward, we use these
practices in the chapter examples and you should use them in your own code.
For more information on this issue, see CERT C Secure Coding rule
FIO30-C
In Chapter 6’s Secure C Programming section, we’ll explain the notion of
user input as referred to by this CERT guideline.
scanf
and printf,
scanf_s and printf_s
We introduced scanf and printf in this chapter. We’ll be saying more about these in sub-sequent Secure
C Coding Guidelines sections. We’ll also discuss scanf_s and printf_s, which
were introduced in C11.
0 comments:
Post a Comment