2. Introduction to C Programming


Objectives

In this chapter you’ll:

Image Write simple C programs.

Image Use simple input and output statements.

Image Use the fundamental data types.

Image Use arithmetic operators.

Image Learn the precedence of arithmetic operators.

Image Write simple decision-making statements.


2.1. Introduction

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 remainder of the text.

2.2. A Simple C Program: Printing a Line of 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! " );
 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 preceding comment simply describes the figure number, file name and purpose of the program.

You can also use /*...*/ multiline 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.

#include Preprocessor Directive

Line 3

#include <stdio.h>

is a directive to the C preprocessor. Lines beginning with # are processed by the preprocessor before compilation. Line 3 tells the preprocessor to include the contents of the standard 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.


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

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 statement. Every statement must end with a semicolon (also known as the statement terminator). 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 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 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 common escape sequences are listed in Fig. 2.2.

Image

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


Image Good Programming Practice 2.2

Add a comment to the line containing the right brace, }, that closes every function, including 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 decision 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 language. 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 functions 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 executable. 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.


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



Image Good Programming Practice 2.4

Set a convention for the size of indent you prefer and then uniformly apply that convention. 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 program 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! " ); 
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 (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 to C! " );
 9   } // end function main


Welcome
to
C!


Fig. 2.4 Printing multiple lines with a single printf.

2.3. Another Simple C Program: Adding Two Integers

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 dialog 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 " ); // prompt
13      scanf( "%d", &integer1 ); // read an integer
14
15      printf( "Enter second integer " ); // prompt
16      scanf( "%d", &integer2 ); // read an integer
17
18      sum = integer1 + integer2; // assign total to sum
19
20      printf( "Sum is %d ", 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—locations 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.

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 variable’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 statement as follows:

int integer1, integer2, sum;

but that would have made it difficult to describe the variables with corresponding comments 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.


Image Error-Prevention Tip 2.1

Avoid starting identifiers with the underscore character (_) to prevent conflicts with compiler-generated identifiers and standard library identifiers.



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



Image 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 before any executable statements. Therefore, in the program in Fig. 2.5, inserting the definition of integer1 after the first printf would cause a syntax error in Visual C++.


Image Common Programming Error 2.1

Placing variable definitions among executable statements causes syntax errors in the Microsoft Visual C++ Compiler.


Prompting Messages

Line 12

printf( "Enter first integer " ); // 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 arguments, "%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 address 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 location. 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 remember to precede each variable in every call to scanf with an ampersand. Some exceptions 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.


Image 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 computing.

Line 15

printf( "Enter second integer " ); // 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 and the + operator are called binary operators because each has two operands. The + operator’s two operands are integer1 and integer2. The = operator’s two operands are sum and the value of the expression integer1 + integer2.


Image 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 ", 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 " and sum. The first argument 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 second 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 ", integer1 + integer2 );

The right brace, }, at line 21 indicates that the end of function main has been reached.


Image Common Programming Error 2.2

Forgetting to precede a variable in a scanf statement with an ampersand when that variable 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.



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


2.4. Arithmetic in C

Most C programs perform calculations using the C arithmetic operators (Fig. 2.6). The asterisk (*) indicates multiplication and the percent sign (%) denotes the remainder operator, 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.

Image

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


Image Common Programming Error 2.4

An attempt to divide by zero is normally undefined on computer systems and generally results in a fatal error, i.e., an error that causes the program to terminate immediately without 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

Image

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. Multiplication, division and remainder operations are applied next. If an expression contains several multiplication, division and remainder operations, evaluation 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 summarizes these rules of operator precedence for the operators we’ve seen so far.

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.

Image

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 calculates the arithmetic mean (average) of five terms.

Image

The parentheses are required to group the additions because division has higher precedence 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

Image

The following expression is the equation of a straight line:

Image

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:

Image

The circled numbers indicate the order in which C evaluates the operators. The multiplication, 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 evaluates a second-degree polynomial.

Image

The circled numbers under the statement indicate the order in which C performs the operations. 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 exponentiation. 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 initialized 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 preceding statement could be parenthesized as follows:

 y = ( a * x * x ) + ( b * x ) + c;

Image

Fig. 2.8 Order in which a second-degree polynomial is evaluated.

2.5. Decision Making: Equality and Relational Operators

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 decision in a program, for example, to determine whether a person’s grade on an exam is greater 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 statement 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 precedence and they associate left to right. The equality operators have a lower level of precedence 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.]

Image

Fig. 2.9 Equality and relational operators.


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


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 " );
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 ", num1, num2 );
19      } // end if                                    
20
21      if ( num1 != num2 ) {
22         printf( "%d is not equal to %d ", num1, num2 );
23      } // end if
24
25      if ( num1 < num2 ) {
26         printf( "%d is less than %d ", num1, num2 );
27      } // end if
28
29      if ( num1 > num2 ) {
30         printf( "%d is greater than %d ", num1, num2 );
31      } // end if
32
33      if ( num1 <= num2 ) {
34         printf( "%d is less than or equal to %d ", num1, num2 );
35      } // end if
36
37      if ( num1 >= num2 ) {
38         printf( "%d is greater than or equal to %d ", 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.

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.


Image Good Programming Practice 2.9

Although it’s allowed, there should be no more than one statement per line in a program.



Image Common Programming Error 2.6

Placing commas (when none are needed) between conversion specifiers in the format control string of a scanf statement.


Comparing Numbers

The if statement in lines 17–19

if ( num1 == num2 ) {
   printf( "%d is equal to %d ", 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.


Image 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

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.


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

Image

Fig. 2.11 Precedence and associativity of the operators discussed so far.


Image Good Programming Practice 2.11

Refer to the operator precedence chart when writing expressions containing many operators. 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 keywords. These words have special meaning to the C compiler, so you must be careful not to use these as identifiers such as variable names.

Image

Fig. 2.12 C’s keywords.

2.6. Secure C Programming

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

should be written as:

puts( "Welcome to C!" );

We did not include 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 conversion 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

www.securecoding.cert.org/confluence/display/seccode/
   FIO30-C.+Exclude+user+input+from+format+strings

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 subsequent Secure C Coding Guidelines sections. We’ll also discuss scanf_s and printf_s, which were introduced in C11.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.244.250