Wednesday 29 March 2017

C FOR PROGRAMMERS WITH AN INTRODUCTION TO C11 DEITEL® DEVELOPER SERIES

                                                 Chapter 2 
                                                   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.


2.2  A Simple C Program: Printing a Line of Text
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.


22        Chapter 2  Introduction to C Programming


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.


2.2  A Simple C Program: Printing a Line of Text
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.


24        Chapter 2  Introduction to C Programming


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.


2.3  Another Simple C Program: Adding Two Integers
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.


26        Chapter 2  Introduction to C Programming


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


2.4  Arithmetic in C
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.


28
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.


2.4  Arithmetic in C
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:     =  -------------------------------------
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.


30        Chapter 2  Introduction to C Programming


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;




2.5  Decision Making: Equality and Relational Operators
31
















Step 1.
y = 2 * 5 * 5 + 3 * 5 + 7;
(Leftmost multiplication)

















2 * 5 is
10


















































Step 2.
y = 10
*
5

+ 3

*

5 + 7;
(Leftmost multiplication)

















10
* 5 is
50




















































Step 3.
y = 50
+
3

* 5

+

7;


(Multiplication before addition)




















3

* 5

is
15













































Step 4.
y = 50
+
15 + 7;





(Leftmost addition)


















50
+
15 is
65




























































Step 5.
y = 65
+
7;











(Last addition)


















65
+
7

is
72
























(Last operation—place 72 in y)





































Step 6.
y = 72


































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.


32
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.)


2.5  Decision Making: Equality and Relational Operators
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.


34        Chapter 2  Introduction to C Programming


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.









2.6  Secure C Programming
35












Operators

Associativity















()



left to right





*
/
%

left to right





+
-


left to right





< 
<=
> 
>=
left to right





==
!=


left to right





=



right to left













Fig. 2.11
Precedence and associativity of the



operators discussed so far.














Keywords


















auto

double


int
struct

break

else



long
switch

case

enum



register

typedef

char

extern


return

union

const

float



short

unsigned

continue

for



signed

void

default

goto



sizeof

volatile

do

if



static

while

Keywords added in C99 standard












_Bool  _Complex  _Imaginary  inline  restrict


Keywords added in C11 standard






_Alignas  _Alignof

_Atomic
_Generic
_Noreturn  _Static_assert
_Thread_local












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.

Avoid Single-Argument printfs

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!" );


36        Chapter 2  Introduction to C Programming


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