0% found this document useful (0 votes)
22 views

C Programming

The document discusses computer programming and the C programming language. It defines what a computer program and programming are, and describes different levels of programming languages from machine language to assembly language to high-level languages like C. It then explains the process of translating programs into machine code that can be executed by computers, and provides details about writing, compiling, and running C programs.

Uploaded by

Dahlia Gamal
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views

C Programming

The document discusses computer programming and the C programming language. It defines what a computer program and programming are, and describes different levels of programming languages from machine language to assembly language to high-level languages like C. It then explains the process of translating programs into machine code that can be executed by computers, and provides details about writing, compiling, and running C programs.

Uploaded by

Dahlia Gamal
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 572

Devi Ahilya Vishvavidyalaya

1/12/2007 School of Computer Science [email protected] 1


What is a Computer Program?

A program is a set of step-by-step


instructions to the computer telling it to
carry out the tasks that you want it to do
to produce the results you want.

1/12/2007 School of Computer Science [email protected] 2


What is Programming?

• Programming consists of two distinct


steps:

• algorithmic design (the problem solving


stage, analogous to the work of an
architect designing a building)

• coding (the construction phase)

1/12/2007 School of Computer Science [email protected] 3


Levels of Programming
Languages
• Machine language
• Assembly Language
• High Level Languages

1/12/2007 School of Computer Science [email protected] 4


Machine Language
• Actual binary code that gives basic
instructions to the computer.
• These are usually simple commands
like adding two numbers or moving
data from one memory location to
another.
• Different for each computer processor

1/12/2007 School of Computer Science [email protected] 5


Assembly Language
• A way for humans to program computers
directly without memorizing strings of binary
numbers.
• There is a one-to-one correspondence with
machine code.
– For example ADD and MOV are mnemonics for
addition and move operations that can be specified
in single machine language instructions.
Different for each computer processor

1/12/2007 School of Computer Science [email protected] 6


High-level language

• Permits humans to write complex


programs without going step-by step.
• High-level languages include Pascal,
FORTRAN, Java, Visual Basic, and
many more.
• One command in a high-level
language may translate to tens of
machine language instructions.

1/12/2007 School of Computer Science [email protected] 7


Translation
Computers can only run machine language
programs directly.
Assembly language programs are assembled, or
translated into machine language.
Likewise, programs written in high-level languages,
like Java, must also be translated into machine
language before they can be run. To do this
translation compile a program.

1/12/2007 School of Computer Science [email protected] 8


Translation
10100110 01110110
#include <stdio.h> 00100110 00000000
11111010 11111010
int main() 01001110 10100110
{ 11100110 10010110
printf(“Hello World”); 11001110 00101110
10100110 01001110
11111010 01100110
return 0;
01001110 10000110
}
etc...

Source code Executable code

• Compilers and linkers translate a high


level program into executable machine
1/12/2007code School of Computer Science [email protected] 9
Structured Programming
• STRUCTURED PROGRAMMING ≡ A
technique for organizing and coding computer
programs in which a hierarchy of modules is
used, each having a single entry and a single
exit point, and in which control is passed
downward through the structure withOUT
UNconditional branches to higher levels of
the structure. Three types of control flow are
used: (1) sequential, (2) selection, and (3)
iteration.

1/12/2007 School of Computer Science [email protected] 10


Programming language C

• C is a general purpose programming language.

• C is a middle level language.

• C is a structured language.

1/12/2007 School of Computer Science [email protected] 11


Programming language C
Why C is called “a middle level language”?

C contains the features of high level language


portability — it is easy to adapt software written
for one type of computer to another type. the
functionality low level language.

- operators such as &, |,>,< etc. simulate to low


level instruction codes.
- Direct manipulation of bits, bytes and addresses.

1/12/2007 School of Computer Science [email protected] 12


Writing C Programs
• A programmer uses a text editor to create or
modify files containing C code.
• Code is also known as source code.
• A file containing source code is called a source
file.
• After a C source file has been created, the
programmer must invoke the C compiler
before the program can be executed (run).

1/12/2007 School of Computer Science [email protected] 13


Invoking the tcc Compiler
At the prompt, type

tcc pgm.c

where pgm.c is the C program source


file.

There is a better way use of IDE instead of


command.

1/12/2007 School of Computer Science [email protected] 14


The Result : pgm.obj, pgm.exe
• If there are no errors in pgm.c, this command
produces an executable file, which is one that
can be executed (run).
• The tcc compiler puts exe extension of the
executable file. Also the obj file contains the
machine level code.
• To execute the program, at the prompt, type
pgm.exe
• Although we call this process “compiling a
program,” what actually happens is more
complicated.
1/12/2007 School of Computer Science [email protected] 15
3 Stages of Compilation
Stage 1: Preprocessing
– Performed by a program called the preprocessor
– Modifies the source code (in RAM) according to
preprocessor directives (preprocessor
commands) embedded in the source code
– Strips comments and white space from the code
– The source code as stored on disk is not modified.

1/12/2007 School of Computer Science [email protected] 16


3 Stages of Compilation (con’t)
Stage 2: Compilation
• Performed by a program called the compiler
• Translates the preprocessor-modified source
code into object code (machine code)
• Checks for syntax errors and warnings
• Saves the object code to a disk file, if instructed
to do so (we will not do this).
• If any compiler errors are received, no object code
file will be generated.
• An object code file will be generated if only
warnings, not errors, are received.
1/12/2007 School of Computer Science [email protected] 17
3 Stages of Compilation (con’t)
Stage 3: Linking
• Combines the program object code with other
object code to produce the executable file.
• The other object code can come from the Run-
Time Library, other libraries, or object files that
you have created.
• Saves the executable code to a disk file. On
the Linux system, that file is called a.out.
• If any linker errors are received, no executable file
will be generated.

1/12/2007 School of Computer Science [email protected] 18


Program Development
Editor

Source File pgm.c

Preprocessor

Modified Source Code in RAM

Compiler
Program Object Code File pgm.obj
Other Object Code Files (if any)

Linker

Executable File pgm.exe


1/12/2007 School of Computer Science [email protected] 19
A Simple C Program
/* Filename: hello.c
Author: Brian Kernighan & Dennis Ritchie
Date written: ?/?/1978
Description: This program prints the greeting
“Hello, World!”
*/
#include <stdio.h>
int main ( void )
{
printf ( “Hello, World!\n” ) ;
return 0 ;
}
1/12/2007 School of Computer Science [email protected] 20
Anatomy of a C Program
program header comment

preprocessor directives (if any)

int main ( )
{
statement(s)
return 0 ;
}
1/12/2007 School of Computer Science [email protected] 21
Program Header Comment
• A comment is descriptive text used to help a
reader of the program understand its
content.
• All comments must begin with the characters
/* and end with the characters */
• These are called comment delimiters
• The program header comment always
comes first.

1/12/2007 School of Computer Science [email protected] 22


Preprocessor Directives
• Lines that begin with a # in column 1 are
called preprocessor directives
(commands).
• Example: the #include <stdio.h> directive
causes the preprocessor to include a copy of
the standard input/output header file stdio.h at
this point in the code.
• This header file was included because it
contains information about the printf ( )
function that is used in this program.
1/12/2007 School of Computer Science [email protected] 23
stdio.h
• When we write our programs, there are
libraries of functions to help us so that we
do not have to write the same code over
and over again.
• Some of the functions are very complex
and long. Not having to write them
ourselves make it easier and faster to
write programs.
• Using the functions will also make it easier
to learn to program!
1/12/2007 School of Computer Science [email protected] 24
int main ( void )
• Every program must have a function called
main. This is where program execution begins.
• main() is placed in the source code file as the
first function for readability.
• The reserved word “int” indicates that main()
returns an integer value.
• The parentheses following the reserved word
“main” indicate that it is a function.
• The reserved word “void” means nothing is
there.
1/12/2007 School of Computer Science [email protected] 25
The Function Body
• A left brace (curly bracket) -- { -- begins the
body of every function. A corresponding
right brace -- } -- ends the function body.

• The style is to place these braces on


separate lines in column 1 and to indent the
entire function body 3 to 5 spaces.

1/12/2007 School of Computer Science [email protected] 26


printf (“Hello, World!\n”) ;
• This line is a C statement.
• It is a call to the function printf ( ) with a
single argument (parameter), namely the
string “Hello, World!\n”.
• Even though a string may contain many
characters, the string itself should be
thought of as a single quantity.
• Notice that this line ends with a semicolon.
All statements in C end with a semicolon.
1/12/2007 School of Computer Science [email protected] 27
return 0 ;
• Because function main() returns an integer value,
there must be a statement that indicates what this
value is.
• The statement
return 0 ;
indicates that main() returns a value of zero to
the operating system.
• A value of 0 indicates that the program successfully
terminated execution.
• Do not worry about this concept now. Just
remember to use the statement.
1/12/2007 School of Computer Science [email protected] 28
Another C Program
/*****************************************
** File: proj1.c
** Author: ___________
** Date: 9/15/01
** E-mail: _________________
**
** This program prompts the user for two integer values then displays
** their product.
**
***********************************************/

1/12/2007 School of Computer Science [email protected] 29


Another C Program (con’t)
#include <stdio.h>
int main( void )
{
int value1, value2, product ;
printf(“Enter two integer values: “) ;
scanf(“%d%d”, &value1, &value2) ;
product = value1 * value2 ;
printf(“Product = %d\n”, product) ;
return 0 ;
}
1/12/2007 School of Computer Science [email protected] 30
Tokens
• The smallest element in the C language is
the token.
• It may be a single character or a sequence
of characters to form a single item.

1/12/2007 School of Computer Science [email protected] 31


Tokens are:

• Tokens can be:


– Numeric constants
– Character constants
– String constants
– Keywords
– Names (identifiers)
– Punctuation
– Operators

1/12/2007 School of Computer Science [email protected] 32


Numeric Constants

• Numeric constants are an uninterrupted


sequence of digits (and may contain a
period). They never contain a comma.
• Examples:
– 123
– 98.6
– 1000000

1/12/2007 School of Computer Science [email protected] 33


Character Constants

• One character from a defined character


set.
• Surrounded on the single quotation mark.
• Examples:
– ‘A’
– ‘a’
– ‘$’
– ‘4’

1/12/2007 School of Computer Science [email protected] 34


String Constants

• A sequence characters surrounded by


double quotation marks.
• Considered a single item.
• Examples:
– “DAVV”
– “I like ice cream.”
– “123”
– “DHOOM-2”
– “car”
1/12/2007 School of Computer Science [email protected] 35
Keywords

• Sometimes called reserved words.


• Are defined as a part of the C language.
• Can not be used for anything else!
• Examples:
– int
– while
– for

1/12/2007 School of Computer Science [email protected] 36


Names
• Sometimes called identifiers.
• Can be of anything length, but on the first 31 are
significant (too long is as bad as too short).
• Are case sensitive:
– abc is different from ABC
• Must begin with a letter and the rest can be
letters, digits, and underscores.
• There can be one exception to beginning letter
that variable name can start with underscore( _ )
but it is used by C library.

1/12/2007 School of Computer Science [email protected] 37


Punctuation

• Semicolons, colons, commas,


apostrophes, quotation marks, braces,
brackets, and parentheses.
• ; : , ‘ “ [ ] { } ( )

1/12/2007 School of Computer Science [email protected] 38


Operators

• There are operators for:


– assignments
– mathematical operations
– relational operations
– Boolean operations
– bitwise operations
– shifting values
– calling functions
– subscripting
– obtaining the size of an object
– obtaining the address of an object
– referencing an object through its address

1/12/2007 School of Computer Science [email protected] 39


What Are Variables in C?
• Variables in C have the same meaning as
variables in algebra. That is, they represent
some unknown, or variable, value.

x=a+b
z + 2 = 3(y - 5)
• Remember that variables in algebra are
represented by a single alphabetic
character.
1/12/2007 School of Computer Science [email protected] 40
Naming Variables
• Variables in C may be given representations
containing multiple characters. But there are
rules for these representations.
• Variable names (identifiers) in C
– May only consist of letters, digits, and
underscores
– May be as long as you like, but only the first 31
characters are significant
– May not begin with a digit
– May not be a C reserved word (keyword)
1/12/2007 School of Computer Science [email protected] 41
Reserved Words (Keywords) in
C

• auto break int long


• case char register return
• const continue short signed
• default do sizeof static
• double else struct switch
• enum extern typedef union
• float for unsigned void
• goto if volatile while

1/12/2007 School of Computer Science [email protected] 42


Naming Conventions
• C programmers generally agree on the
following conventions for naming variables.
– Begin variable names with lowercase letters
– Use meaningful identifiers
– Separate “words” within identifiers with
underscores or mixed upper and lower case.
– Examples: surfaceArea surface_Area
surface_area
– Be consistent!

1/12/2007 School of Computer Science [email protected] 43


Naming Conventions (con’t)
• Use all uppercase for symbolic constants
(used in #define preprocessor directives).
• Note: symbolic constants are not variables,
but make the program easier to read.
• Examples:
#define PI 3.14159
#define AGE 52

1/12/2007 School of Computer Science [email protected] 44


Case Sensitivity
• C is case sensitive
– It matters whether an identifier, such as a
variable name, is uppercase or lowercase.
– Example:
area
Area
AREA
ArEa
are all seen as different variables by the
compiler.
1/12/2007 School of Computer Science [email protected] 45
Which Are Legal Identifiers?
AREA area_under_the_curve
3D num45
Last-Chance #values
x_yt3 pi
num$ %done
lucky***

1/12/2007 School of Computer Science [email protected] 46


Declaring Variables
• Before using a variable, you must give the
compiler some information about the variable;
i.e., you must declare it.
• The declaration statement includes the data
type of the variable.
• They must be declared just after the start of
block (i.e. start of a function) and before any
other executable statement.
• Examples of variable declarations:
int meatballs ;
float area ;

1/12/2007 School of Computer Science [email protected] 47


Declaring Variables (con’t)
• When we declare a variable
– Space is set aside in memory to hold a value of
the specified data type
– That space is associated with the variable name
– That space is associated with a unique address
• Visualization of the declaration
int meatballs ;
meatballs
garbage

FE07 int
1/12/2007 School of Computer Science [email protected] 48
Notes About Variables

• You must not use a variable until you


somehow give it a value.
• You can not assume that the variable will
have a value before you give it one.
– Some compilers do, others do not! This is the
source of many errors that are difficult to find.

1/12/2007 School of Computer Science [email protected] 49


Simple Data Types
Type Typical Size in Bits Minimal Range
char 8 –128 to 127
unsigned char 8 0 to 255
signed char 8 –128 to 127
int 16 –32,768 to 32,767
unsigned int 16 0 to 65,535
signed int 16 Same as int
short int 16 –32,768 to 32,767
unsigned short int 16 0 to 65,535
signed short int 16 Same as short int
long int 32 –2,147,483,648 to 2,147,483,647
signed long int 32 Same as long int
unsigned long int 32 0 to 4,294,967,295
float 32 1E–37 to 1E+37 with six digits of precision
double 64 1E–37 to 1E+37 with ten digits of precision
long double 80 1E–37 to 1E+37 with ten digits of precision
1/12/2007 School of Computer Science [email protected] 50
Using Variables: Initialization
• Variables may be be given initial values, or
initialized, when declared. Examples:
length
int length = 7 ; 7

diameter
float diameter = 5.9 ; 5.9

initial
char initial = ‘A’ ; ‘A’

1/12/2007 School of Computer Science [email protected] 51


Using Variables: Assignment
• Variables may have values assigned to them through
the use of an assignment statement.
• Such a statement uses the assignment operator =
• This operator does not denote equality. It assigns
the value of the right-hand side of the statement (the
expression) to the variable on the left-hand side.
• Examples:
diameter = 5.9 ;
area = length * width ;
Note that only single variables (LValue) may appear
on the left-hand side of the assignment operator.
1/12/2007 School of Computer Science [email protected] 52
Functions
• It is necessary for us to use some functions to
write our first programs.
• Functions are parts of programs that perform a
certain task and we have to give them some
information so the function can do the task.
• We will show you how to use the functions as we
go through the course and later on will show you
how to create your own.

1/12/2007 School of Computer Science [email protected] 53


Getting Input from User
• Every process requires some input from
the user. Variables hold the input values.
• We have a function called scanf( ) that will
allow us to do that.
• The function scanf needs two pieces of
information to display things.
– The data type of input values
– Address where to store the values
• scanf( “%f”, &diameter );
1/12/2007 School of Computer Science [email protected] 54
Displaying Variables
• Variables hold values that we occasionally
want to show the person using the
program.
• We have a function called printf( ) that will
allow us to do that.
• The function printf needs two pieces of
information to display things.
– How to display it
– What to display
• printf( “%f\n”, &diameter );
1/12/2007 School of Computer Science [email protected] 55
printf( “%f\n”, diameter );

• The name of the function is “printf”.


• Inside the parentheses are:
– print specification, where we are going to
display:
• a floating point value (“%f”)
• We want to have the next thing started on a new
line (“\n”).
– We want to display the contents of the
variable diameter.
• printf( ) has many other capabilities.
1/12/2007 School of Computer Science [email protected] 56
Backslash Codes
Code Meaning
\b Backspace
\f Form feed
\n New line
\r Carriage return
\t Horizontal tab
\" Double quote
\' Single quote
\\ Backslash
\v Vertical tab
\a Alert
\? Question mark
\N Octal constant (where N is an octal constant)
\xN Hexadecimal constant (where N is a hexadecimal constant)
1/12/2007 School of Computer Science [email protected] 57
Format Specifiers for printf and
scanf
Data Type Printf specifier Scanf specifier

long double %Lf %Lf


double %f %lf
float %f %f
unsigned long int %lu %lu
long int %ld %ld
unsigned int %u %u
int %d %d
short %hd %hd
char %c %c
1/12/2007 School of Computer Science [email protected] 58
Both printf and scanf Returns a
Value
• We can call printf as
i=810;
n=printf(“%d”,i);

• We also can call a scanf


m=scanf(“%d%f”,&i,&f)

What will be the value of n & m if every thing


goes fine.
1/12/2007 School of Computer Science [email protected] 59
Example: Declarations and
Assignments
#include <stdio.h> inches
garbage
int main( void ) feet
garbage
{
fathoms
int inches, feet, fathoms ; garbage
fathoms
fathoms = 7 ; 7
feet = 6 * fathoms ; feet
42
inches = 12 * feet ; inches
– 504

1/12/2007 School of Computer Science [email protected] 60


Example: Declarations and
Assignments (cont’d)



printf (“Its depth at sea: \n”) ;
printf (“ %d fathoms \n”, fathoms) ;
printf (“ %d feet \n”, feet) ;
printf (“ %d inches \n”, inches) ;

return 0 ;
}

1/12/2007 School of Computer Science [email protected] 61


Enhancing Our Example
• What if the depth were really 5.75
fathoms? Our program, as it is, couldn’t
handle it.
• Unlike integers, floating point numbers can
contain decimal portions. So, let’s use
floating point, rather than integer.
• Let’s also ask the user to enter the number
of fathoms, by using the scanf( ) function.

1/12/2007 School of Computer Science [email protected] 62


Enhanced Program
#include <stdio.h>
int main ( void )
{
float inches, feet, fathoms ;
printf (“Enter the depth in fathoms : ”) ;
scanf (“%f”, &fathoms) ;
feet = 6 * fathoms ;
inches = 12 * feet ;
printf (“Its depth at sea: \n”) ;
printf (“ %f fathoms \n”, fathoms) ;
printf (“ %f feet \n”, feet) ;
printf (“ %f inches \n”, inches) ;
return 0 ;
}
1/12/2007 School of Computer Science [email protected] 63
scanf (“%f”, &fathoms) ;

• The scanf( ) function also needs two items:


– The input specification “%f”. (Never put a “\n”
into the input specification.)
– The address of where to store the information.
(We can input more than one item at a time if
we wish, as long as we specify it correctly.)
• Notice the “&” in front of the variable name.
It says to use the address of the variable to
hold the information that the user enters.

1/12/2007 School of Computer Science [email protected] 64


Final “Clean” Program
#include <stdio.h>

#define FEET_PER_FATHOM 6
#define INCHES_PER_FOOT 12

int main( void )


{
float inches ; /* number of inches deep */
float feet ; /* number of feet deep */
float fathoms ; /* number of fathoms deep */

/* Get the depth in fathoms from the user */


printf (“Enter the depth in fathoms : ”) ;
scanf (“%f”, &fathoms) ;
1/12/2007 School of Computer Science [email protected] 65
Final “Clean” Program (con’t)

/* Convert the depth to inches */


feet = FEET_PER_FATHOM * fathoms ;
inches = INCHES_PER_FOOT * feet ;

/* Display the results */


printf (“Its depth at sea: \n”) ;
printf (“ %f fathoms \n”, fathoms) ;
printf (“ %f feet \n”, feet);
printf (“ %f inches \n”, inches);
return 0 ;
}

1/12/2007 School of Computer Science [email protected] 66


Good Programming Practices
• Place each variable declaration on its own
line with a descriptive comment.
• Place a comment before each logical
“chunk” of code describing what it does.
• Do not place a comment on the same line as
code (with the exception of variable
declarations).
• Use spaces around all arithmetic and
assignment operators.
• Use blank lines to enhance readability.
1/12/2007 School of Computer Science [email protected] 67
Good Programming Practices
(con’t)
• Place a blank line between the last
variable declaration and the first
executable statement of the program.
• Indent the body of the program 3 to 5
spaces -- be consistent!
• Comments should explain why you are
doing something, not what you are doing
it.
a = a + 1 /* add one to a */ /* WRONG */
/* count new student */ /* RIGHT*/
1/12/2007 School of Computer Science [email protected] 68
Another Sample Program
#include <stdio.h>

#define PI 3.14159

int main ( void )


{
float radius = 3.0;
float area;

area = PI * radius * radius;


printf( “The area is %f.\n”, area );
return 0 ;
}

1/12/2007 School of Computer Science [email protected] 69


Arithmetic Operators in C
Name Operator Example

Addition + num1 + num2


Subtraction - initial - spent
Multiplication * fathoms * 6
Division / sum / count
Modulus % m%n

1/12/2007 School of Computer Science [email protected] 70


Division
• If both operands of a division expression are
integers, you will get an integer answer.
The fractional portion is thrown away.
• Examples : 17 / 5 = 3
4 / 3 = 1
35 / 9 = 3

1/12/2007 School of Computer Science [email protected] 71


Division (con’t)

• Division where at least one operand is a


floating point number will produce a
floating point answer.
• Examples : 17.0 / 5 = 3.4
4 / 3.2 = 1.25
35.2 / 9.1 = 3.86813
• What happens? The integer operand is
temporarily converted to a floating point,
then the division is performed.
1/12/2007 School of Computer Science [email protected] 72
Division By Zero
• Division by zero is mathematically
undefined.
• If you allow division by zero in a program,
it will cause a fatal error. Your program
will terminate execution and give an error
message.
• Non-fatal errors do not cause program
termination, just produce incorrect results.

1/12/2007 School of Computer Science [email protected] 73


Modulus
• The expression m % n yields the integer
remainder after m is divided by n.
• Modulus is an integer operation -- both
operands MUST be integers.
• Examples : 17 % 5 = 2
6%3 = 0
9%2 = 1
5%8 = 5

1/12/2007 School of Computer Science [email protected] 74


Uses for Modulus
• Used to determine if an integer value is
even or odd
5 % 2 = 1 odd 4 % 2 = 0 even
If you take the modulus by 2 of an integer,
a result of 1 means the number is odd and
a result of 0 means the number is even.

1/12/2007 School of Computer Science [email protected] 75


Arithmetic Operators
Rules of Operator Precedence
Operator(s) Precedence & Associativity
() Evaluated first. If nested,
innermost first. If on same level,
evaluated left to right.
* / % Evaluated second. If there are
several, evaluated left to right.
+ - Evaluated third. If there are
several, evaluated left to right.
= Evaluated last, right to left.

1/12/2007 School of Computer Science [email protected] 76


Using Parentheses
• Use parentheses to change the order in
which an expression is evaluated.
a+b*c Would multiply b * c first,
then add a to the result.
If you really want the sum of a and b to be
multiplied by c, use parentheses to force the
evaluation to be done in the order you want.
(a + b) * c
• Also use parentheses to clarify a complex
expression.
1/12/2007 School of Computer Science [email protected] 77
Practice With Evaluating
Expressions
Given integer variables a, b, c, d, and e,
where a = 1, b = 2, c = 3, d = 4,
evaluate the following expressions:
a+b-c+d
a*b/c
1+a*b%c
a+d%b-c
e=b=d+c/b-a
1/12/2007 School of Computer Science [email protected] 78
Relational Operators
< less than
> greater than
<= less than or equal to
>= greater than or equal to
== is equal to
!= is not equal to

Relational expressions evaluate to the integer


values 1 (true) or 0 (false).
All of these operators are called binary operators
because they take two expressions as operands.
1/12/2007 School of Computer Science [email protected] 79
Practice with Relational
Expressions
int a = 1, b = 2, c = 3 ;
Expression Value Expression Value
a < c a + b >= c
b <= c a + b == c
c <= a a != b
a>b a + b != c
b >= c

1/12/2007 School of Computer Science [email protected] 80


Arithmetic Expressions: True or
False
• Arithmetic expressions evaluate to
numeric values.

• An arithmetic expression that has a value


of zero is false.

• An arithmetic expression that has a value


other than zero is true.

1/12/2007 School of Computer Science [email protected] 81


Practice with Arithmetic
Expressions
int a = 1, b = 2, c = 3 ;
float x = 3.33, y = 6.66 ;
Expression Numeric Value True/False
a+b
b-2*a
c-b-a
c-a
y-x
y-2*x
1/12/2007 School of Computer Science [email protected] 82
Increment and Decrement
Operators
• The increment operator ++
• The decrement operator --
• Precedence: lower than (), but higher than
* / and %
• Associativity: right to left
• Increment and decrement operators can
only be applied to variables, not to
constants or expressions

1/12/2007 School of Computer Science [email protected] 83


Increment Operator
• If we want to add one to a variable, we can
say:
count = count + 1 ;
• Programs often contain statements that
increment variables, so to save on typing, C
provides these shortcuts:
count++ ; OR ++count ;
Both do the same thing. They change the
value of count by adding one to it.

1/12/2007 School of Computer Science [email protected] 84


Postincrement Operator
• The position of the ++ determines when the value
is incremented. If the ++ is after the variable, then
the incrementing is done last (a postincrement).
int amount, count ;
count = 3 ;
amount = 2 * count++ ;

• amount gets the value of 2 * 3, which is 6, and


then 1 gets added to count.
• So, after executing the last line, amount is 6 and
count is 4.
1/12/2007 School of Computer Science [email protected] 85
Preincrement Operator
• If the ++ is before the variable, then the
incrementing is done first (a preincrement).
int amount, count ;
count = 3 ;
amount = 2 * ++count ;

• 1 gets added to count first, then amount gets the


value of 2 * 4, which is 8.
• So, after executing the last line, amount is 8 and
count is 4.

1/12/2007 School of Computer Science [email protected] 86


Code Example Using ++
#include <stdio.h>
int main ( )
{
int i = 1 ;
/* count from 1 to 10 */
while ( i < 11 )
{
printf (“%d ”, i) ;
i++ ; /* same as ++i */
}
return 0 ;
}

1/12/2007 School of Computer Science [email protected] 87


Decrement Operator
• If we want to subtract one from a variable, we
can say:
count = count - 1 ;
• Programs often contain statements that
decrement variables, so to save on typing, C
provides these shortcuts:
count-- ; OR --count ;
Both do the same thing. They change the
value of count by subtracting one from it.

1/12/2007 School of Computer Science [email protected] 88


Postdecrement Operator
• The position of the -- determines when the value is
decremented. If the -- is after the variable, then
the decrementing is done last (a postdecrement).
int amount, count ;
count = 3 ;
amount = 2 * count-- ;

• amount gets the value of 2 * 3, which is 6, and


then 1 gets subtracted from count.
• So, after executing the last line, amount is 6 and
count is 2.
1/12/2007 School of Computer Science [email protected] 89
Predecrement Operator
• If the -- is before the variable, then the
decrementing is done first (a predecrement).
int amount, count ;
count = 3 ;
amount = 2 * --count ;

• 1 gets subtracted from count first, then amount


gets the value of 2 * 2, which is 4.
• So, after executing the last line, amount is 4 and
count is 2.

1/12/2007 School of Computer Science [email protected] 90


A Hand Trace Example
int answer, value = 4 ;
Code Value Answer
4 garbage
value = value + 1 ;
value++ ;
++value ;
answer = 2 * value++ ;
answer = ++value / 2 ;
value-- ;
--value ;
answer = --value * 2 ;

1/12/2007 School of Computer Science [email protected] 91


Lvalue Required

answer++ = value-- / 3 ;

• In C any value that is having an address is


called an Lvalue.

1/12/2007 School of Computer Science [email protected] 92


Practice
Given
int a = 1, b = 2, c = 3 ;

What is the value of this expression?

++a * b - c--

What are the new values of a, b, and c?

1/12/2007 School of Computer Science [email protected] 93


More Practice
Given
int a = 1, b = 2, c = 3, d = 4 ;

What is the value of this expression?

++b / c + a * d++

What are the new values of a, b, c, and d?

1/12/2007 School of Computer Science [email protected] 94


Assignment Operators
= += -= *= /= %=
Statement Equivalent Statement
a=a+2; a += 2 ;
a=a-3; a -= 3 ;
a=a*2; a *= 2 ;
a=a/4; a /= 4 ;
a=a%2; a %= 2 ;
b=b+(c+2); b += c + 2 ;
d=d*(e-5); d *= e - 5 ;
1/12/2007 School of Computer Science [email protected] 95
Practice with Assignment
Operators
int i = 1, j = 2, k = 3, m = 4 ;

Expression Value
i += j + k

j *= k = m + 5

k -= m /= j * 2

1/12/2007 School of Computer Science [email protected] 96


Code Example Using /= and ++
Counting the Digits in an Integer
#include <stdio.h>
int main ( )
{
int num, temp, digits = 0 ;
temp = num = 4327 ;
while ( temp > 0 )
{
printf (“%d\n”, temp) ;
temp /= 10 ;
digits++ ;
}
printf (“There are %d digits in %d.\n”, digits, num) ;
return 0 ;
}

1/12/2007 School of Computer Science [email protected] 97


Operator Precedence and
Associativity
Precedence Associativity

() left to right/inside-out
++ -- ! + (unary) - (unary) (type) right to left
* / % left to right
+ (addition) - (subtraction) left to right
< <= > >= left to right
== != left to right
&& left to right
|| left to right
= += -= *= /= %= right to left
, (comma) right to left
1/12/2007 School of Computer Science [email protected] 98
Review: Structured
Programming
• All programs can be written in terms of
only three control structures
– The sequence structure
• Unless otherwise directed, the statements are
executed in the order in which they are written.
– The selection structure
• Used to choose among alternative courses of
action.
– The repetition structure
• Allows an action to be repeated while some
condition remains true.
1/12/2007 School of Computer Science [email protected] 99
Selection: the if statement

if ( condition )
{
statement(s) /* body of the if statement */
}

The braces are not required if the body contains


only a single statement. However, they are a
good idea and are required by the 104 C Coding
Standards.

1/12/2007 School of Computer Science [email protected] 100


Examples
if ( age >= 18 )
{
printf(“Vote!\n”) ;
}

if ( value == 0 )
{
printf (“The value you entered was zero.\n”) ;
printf (“Please try again.\n”) ;
}
1/12/2007 School of Computer Science [email protected] 101
Good Programming Practice

• Always place braces around the body of


an if statement.
• Advantages:
– Easier to read
– Will not forget to add the braces if you go
back and add a second statement to the body
– Less likely to make a semantic error
• Indent the body of the if statement 3 to 5
spaces -- be consistent!
1/12/2007 School of Computer Science [email protected] 102
Selection: the if-else statement
if ( condition )
{
statement(s) /* the if clause */
}
else
{
statement(s) /* the else clause */
}
1/12/2007 School of Computer Science [email protected] 103
Example
if ( age >= 18 )
{
printf(“Vote!\n”) ;
}
else
{
printf(“Maybe next time!\n”) ;
}
1/12/2007 School of Computer Science [email protected] 104
Example

if ( value == 0 )
{
printf (“The value you entered was zero.\n”) ;
printf(“Please try again.\n”) ;
}
else
{
printf (“Value = %d.\n”, value) ;
}
1/12/2007 School of Computer Science [email protected] 105
Good Programming Practice
• Always place braces around the bodies of
the if and else clauses of an if-else
statement.
• Advantages:
– Easier to read
– Will not forget to add the braces if you go back
and add a second statement to the clause
– Less likely to make a semantic error
• Indent the bodies of the if and else clauses
3 to 5 spaces -- be consistent!
1/12/2007 School of Computer Science [email protected] 106
The Conditional Operator
expr1 ? expr2 : expr3

If expr1 is true then expr2 is executed, else expr3 is evaluated,


i.e.:

x = ((y < z) ? y : z);

OR

(y < z) ? printf(“%d is smaller”,y): printf(“%d is smaller”,y);

1/12/2007 School of Computer Science [email protected] 107


Nesting of if-else Statements
if ( condition1 )
{
statement(s)
}
else if ( condition2 )
{
statement(s)
}
... /* more else clauses may be here */
else
{
statement(s) /* the default case */
}

1/12/2007 School of Computer Science [email protected] 108


Example
if ( value == 0 )
{
printf (“The value you entered was zero.\n”) ;
}
else if ( value < 0 )
{
printf (“%d is negative.\n”, value) ;
}
else
{
printf (“%d is positive.\n”, value) ;
}
1/12/2007 School of Computer Science [email protected] 109
Gotcha! = versus ==
int a = 2 ;

if ( a = 1 ) /* semantic (logic) error! */


{
printf (“a is one\n”) ;
}
else if ( a == 2 )
{
printf (“a is two\n”) ;
}
else
{
printf (“a is %d\n”, a) ;
}
1/12/2007 School of Computer Science [email protected] 110
Gotcha (con’t)
• The statement if (a = 1) is syntactically correct,
so no error message will be produced. (Some
compilers will produce a warning.) However, a
semantic (logic) error will occur.

• An assignment expression has a value -- the


value being assigned. In this case the value
being assigned is 1, which is true.

• If the value being assigned was 0, then the


expression would evaluate to 0, which is false.
1/12/2007 School of Computer Science [email protected] 111
Logical Operators
• So far we have seen only simple conditions.
if ( count > 10 ) . . .
• Sometimes we need to test multiple conditions in
order to make a decision.
• Logical operators are used for combining simple
conditions to make complex conditions.
&& is AND if ( x > 5 && y < 6 )
|| is OR if ( z == 0 || x > 10 )
! is NOT if (! (bob > 42) )
1/12/2007 School of Computer Science [email protected] 112
Example Use of &&

if ( age < 1 && gender == ‘m’)


{
printf (“Infant boy\n”) ;
}

1/12/2007 School of Computer Science [email protected] 113


Truth Table for &&

Expression1 Expression2 Expression1 && Expression2

0 0 0
0 nonzero 0
nonzero 0 0
nonzero nonzero 1

Exp1 && Exp2 && … && Expn will evaluate to 1 (true)


only if ALL subconditions are true.

1/12/2007 School of Computer Science [email protected] 114


Example Use of ||

if (grade == ‘D’ || grade == ‘F’)


{
printf (“See with your Juniors !\n”) ;
}

1/12/2007 School of Computer Science [email protected] 115


Truth Table for ||

Expression1 Expression2 Expression1 || Expression2

0 0 0
0 nonzero 1
nonzero 0 1
nonzero nonzero 1

Exp1 && Exp2 && … && Expn will evaluate to 1


(true) if only ONE subcondition is true.

1/12/2007 School of Computer Science [email protected] 116


Example Use of !

if ( ! (x == 2) ) /* same as (x != 2) */
{
printf(“x is not equal to 2.\n”) ;
}

1/12/2007 School of Computer Science [email protected] 117


Truth Table for !

Expression ! Expression

0 1
nonzero 0

1/12/2007 School of Computer Science [email protected] 118


Gotcha! && or ||
int a = 0 ;
int b=1;
if ( (a++ == 1) && (b++==1 ) ) /* semantic (logic) error! */
{
printf (“First Gotcha\n”) ;
}
else if ( (a++ == 0) || (b++==1 ) )
{
printf (“Second Gotcha\n”) ;
}
else
{
printf (“a is %d\n”, a) ;
}
1/12/2007 School of Computer Science [email protected] 119
Gotcha (con’t)
• While evaluating a condition if first subpart of a
Complex condition having && operator is false
than the remaining subpart will not be evaluated.

• Similarly While evaluating a condition if first


subpart of a Complex condition having || operator
is true than the remaining subpart will not be
evaluated.

1/12/2007 School of Computer Science [email protected] 120


Some Practice Expressions
int a = 1, b = 0, c = 7;

Expression Numeric Value True/False


a
b
c
a+b
a && b
a || b
!c
!!c
a && !b
a < b && b < c
a > b && b < c
a >= b || b > c
1/12/2007 School of Computer Science [email protected] 121
More Practice
Given
int a = 5, b = 7, c = 17 ;
evaluate each expression as True or False.
1. c / b == 2
2. c % b <= a % b
3. b + c / a != c - a
4. (b < c) && (c == 7)
5. (c + 1 - b == 0) || (b = 5)

1/12/2007 School of Computer Science [email protected] 122


Review: Repetition Structure

• A repetition structure allows the programmer


to specify that an action is to be repeated while
some condition remains true.
• There are three repetition structures in C, the
while loop, the for loop, and the do-while loop.

1/12/2007 School of Computer Science [email protected] 123


The while Repetition Structure
while ( condition )
{
statement(s)
}

The braces are not required if the loop body


contains only a single statement. However, they
are a good idea and are required by the 104 C
Coding Standards.

1/12/2007 School of Computer Science [email protected] 124


Parts of a While Loop

• Every while loop will always contain


three main elements:
– Priming: initialize your variables.
– Testing: test against some known condition.
– Updating: update the variable that is tested.

125
Simple While Loop
OUTPUT:
Index: 1

#include <stdio.h> Index: 2


Index: 3
#define MAX 10 Index: 4
main () 1. Priming
Index: 5
{ Index: 6
2. Test Condition
Index: 7
int index =1;
Index: 8
while (index <= MAX) { Index: 9
printf ("Index: %d\n", index);Index: 10
index = index + 1;
3. Update
}
}

126
Example
while ( children > 0 )
{
children = children - 1 ;
cookies = cookies * 2 ;
}

1/12/2007 School of Computer Science [email protected] 127


Good Programming Practice

• Always place braces around the body of a


while loop.
• Advantages:
– Easier to read
– Will not forget to add the braces if you go
back and add a second statement to the loop
body
– Less likely to make a semantic error
• Indent the body of a while loop 3 to 5
spaces -- be consistent!
1/12/2007 School of Computer Science [email protected] 128
Another while Loop Example
• Problem: Write a program that calculates
the average exam grade for a class of 10
students.
• What are the program inputs?
– the exam grades
• What are the program outputs?
– the average exam grade

1/12/2007 School of Computer Science [email protected] 129


The Pseudocode
<total> = 0
<grade_counter> = 1

While (<grade_counter> <= 10)


Display “Enter a grade: ”
Read <grade>
<total> = <total> + <grade>
<grade_counter> = <grade_counter> + 1
End_while
<average> = <total> / 10
Display “Class average is: “, <average>

1/12/2007 School of Computer Science [email protected] 130


The C Code
#include <stdio.h>
int main ( )
{
int counter, grade, total, average ;
total = 0 ;
counter = 1 ;
while ( counter <= 10 )
{
printf (“Enter a grade : “) ;
scanf (“%d”, &grade) ;
total = total + grade ;
counter = counter + 1 ;
}
average = total / 10 ;
printf (“Class average is: %d\n”, average) ;
return 0 ;
}
1/12/2007 School of Computer Science [email protected] 131
Versatile?

• How versatile is this program?


• It only works with class sizes of 10.
• We would like it to work with any class size.
• A better way :
– Ask the user how many students are in the
class. Use that number in the condition of the
while loop and when computing the average.

1/12/2007 School of Computer Science [email protected] 132


New Pseudocode
<total> = 0
<grade_counter> = 1
Display “Enter the number of students: “
Read <num_students>
While (<grade_counter> <= <num_students>)
Display “Enter a grade: ”
Read <grade>
<total> = <total> + <grade>
<grade_counter> = <grade_counter> + 1
End_while
<average> = <total> / <num_students>
Display “Class average is: “, <average>

1/12/2007 School of Computer Science [email protected] 133


New C Code
#include <stdio.h>
int main ( )
{
int numStudents, counter, grade, total, average ;
total = 0 ;
counter = 1 ;
printf (“Enter the number of students: “) ;
scanf (“%d”, &numStudents) ;
while ( counter <= numStudents) {
printf (“Enter a grade : “) ;
scanf (“%d”, &grade) ;
total = total + grade ;
counter = counter + 1 ;
}
average = total / numStudents ;
printf (“Class average is: %d\n”, average) ;
return 0 ;
}
1/12/2007 School of Computer Science [email protected] 134
Why Bother to Make It Easier?
• Why do we write programs?
– So the user can perform some task
• The more versatile the program, the more
difficult it is to write. BUT it is more useable.
• The more complex the task, the more difficult
it is to write. But that is often what a user
needs.
• Always consider the user first.

1/12/2007 School of Computer Science [email protected] 135


Using a Sentinel Value
• We could let the user keep entering grades
and when he’s done enter some special
value that signals us that he’s done.
• This special signal value is called a
sentinel value.
• We have to make sure that the value we
choose as the sentinel isn’t a legal value.
For example, we can’t use 0 as the sentinel
in our example as it is a legal value for an
exam score.
1/12/2007 School of Computer Science [email protected] 136
The Priming Read
• When we use a sentinel value to control a
while loop, we have to get the first value
from the user before we encounter the
loop so that it will be tested and the loop
can be entered.
• This is known as a priming read.
• We have to give significant thought to the
initialization of variables, the sentinel
value, and getting into the loop.

1/12/2007 School of Computer Science [email protected] 137


New Pseudocode
<total> = 0
<grade_counter> = 1
Display “Enter a grade: “
Read <grade>
While ( <grade> != -1 )
<total> = <total> + <grade>
<grade_counter> = <grade_counter> + 1
Display “Enter another grade: ”
Read <grade>
End_while
<average> = <total> / <grade_counter>
Display “Class average is: “, <average>

1/12/2007 School of Computer Science [email protected] 138


New C Code
#include <stdio.h>
int main ( )
{
int counter, grade, total, average ;
total = 0 ;
counter = 1 ;
printf(“Enter a grade: “) ;
scanf(“%d”, &grade) ;
while (grade != -1) {
total = total + grade ;
counter = counter + 1 ;
printf(“Enter another grade: “) ;
scanf(“%d”, &grade) ;
}
average = total / counter ;
printf (“Class average is: %d\n”, average) ;
return 0 ;
}
1/12/2007 School of Computer Science [email protected] 139
Final “Clean” C Code
#include <stdio.h>
int main ( )
{
int counter ; /* counts number of grades entered */
int grade ; /* individual grade */
int total; /* total of all grades */
int average ; /* average grade */

/* Initializations */
total = 0 ;
counter = 1 ;

1/12/2007 School of Computer Science [email protected] 140


Final “Clean” C Code (con’t)
/* Get grades from user */
/* Compute grade total and number of grades */

printf(“Enter a grade: “) ;
scanf(“%d”, &grade) ;
while (grade != -1) {
total = total + grade ;
counter = counter + 1 ;
printf(“Enter another grade: “) ;
scanf(“%d”, &grade) ;
}

/* Compute and display the average grade */


average = total / counter ;
printf (“Class average is: %d\n”, average) ;

return 0 ;
}
1/12/2007 School of Computer Science [email protected] 141
Using a while Loop to Check
#include <stdio.h>
User Input
int main ( )
{
int number ;
printf (“Enter a positive integer : “) ;
scanf (“%d”, &number) ;
while ( number <= 0 )
{
printf (“\nThat’s incorrect. Try again.\n”) ;
printf (“Enter a positive integer: “) ;
scanf (“%d”, &number) ;
}
printf (“You entered: %d\n”, number) ;
return 0 ;
}

1/12/2007 School of Computer Science [email protected] 142


Counter-Controlled Repetition
(Definite Repetition)
• If it is known in advance exactly how many
times a loop will execute, it is known as a
counter-controlled loop.
int i = 1 ;
while ( i <= 10 )
{
printf(“i = %d\n”, i) ;
i=i+1;
}

1/12/2007 School of Computer Science [email protected] 143


Counter-Controlled Repetition
(con’t)
• Is the following loop a counter-controlled
loop?

while ( x != y )
{
printf(“x = %d”, x) ;
x=x+2;
}

1/12/2007 School of Computer Science [email protected] 144


Event-Controlled Repetition
(Indefinite Repetition)
• If it is NOT known in advance exactly how
many times a loop will execute, it is known
as an event-controlled loop.
sum = 0 ;
printf(“Enter an integer value: “) ;
scanf(“%d”, &value) ;
while ( value != -1) {
sum = sum + value ;
printf(“Enter another value: “) ;
scanf(“%d”, &value) ;
}
1/12/2007 School of Computer Science [email protected] 145
Event-Controlled Repetition
(con’t)
• An event-controlled loop will terminate
when some event occurs.
• The event may be the occurrence of a
sentinel value, as in the previous example.
• There are other types of events that may
occur, such as reaching the end of a data
file.

1/12/2007 School of Computer Science [email protected] 146


The 3 Parts of a Loop
#include <stdio.h>
int main ()
{
int i = 1 ; initialization of loop control variable

/* count from 1 to 100 */


while ( i < 101 ) test of loop termination condition
{
printf (“%d “, i) ;
i=i+1; modification of loop control
} variable
return 0 ;
}

1/12/2007 School of Computer Science [email protected] 147


The for Loop Repetition
Structure
• The for loop handles details of the counter-controlled
loop “automatically”.
• The initialization of the the loop control variable, the
termination condition test, and control variable
modification are handled in the for loop structure.

for ( i = 1; i < 101; i = i + 1)


{
initialization modification
} test

1/12/2007 School of Computer Science [email protected] 148


When Does a for Loop Initialize, Test
and Modify?
• Just as with a while loop, a for loop
– initializes the loop control variable before
beginning the first loop iteration,
– modifies the loop control variable at the very
end of each iteration of the loop, and
– performs the loop termination test before each
iteration of the loop.
• The for loop is easier to write and read for
counter-controlled loops.

1/12/2007 School of Computer Science [email protected] 149


A for Loop That Counts From 0
to 9
for ( i = 0; i < 10; i = i + 1 )
{
printf (“%d\n”, i) ;
}

1/12/2007 School of Computer Science [email protected] 150


We Can Count Backwards, Too

for ( i = 9; i >= 0; i = i - 1 )
{
printf (“%d\n”, i) ;
}

1/12/2007 School of Computer Science [email protected] 151


We Can Count By 2’s ... or 7’s
… or Whatever

for ( i = 0; i < 10; i = i + 2 )


{
printf (“%d\n”, i) ;
}

1/12/2007 School of Computer Science [email protected] 152


The do-while Repetition
Structure
do
{
statement(s)
} while ( condition ) ;

• The body of a do-while is ALWAYS


executed at least once. Is this true of a
while loop? What about a for loop?

1/12/2007 School of Computer Science [email protected] 153


Example
do
{
printf (“Enter a positive number: “) ;
scanf (“%d”, &num) ;
if ( num <= 0 )
{
printf (“\nThat is not positive. Try again\n”) ;
}
} while ( num <= 0 ) ;

1/12/2007 School of Computer Science [email protected] 154


An Equivalent while Loop
printf (“Enter a positive number: “) ;
scanf (“%d”, &num) ;
while ( num <= 0 )
{
printf (“\nThat is not positive. Try again\n”) ;
printf (“Enter a positive number: “) ;
scanf (“%d”, &num) ;
}

• Notice that using a while loop in this case


requires a priming read.

1/12/2007 School of Computer Science [email protected] 155


An Equivalent for Loop
printf (“Enter a positive number: “) ;
scanf (“%d”, &num) ;
for ( ; num <= 0; )
{
printf (“\nThat is not positive. Try again\n”) ;
printf (“Enter a positive number: “) ;
scanf (“%d”, &num) ;
}

• A for loop is a very awkward choice here because


the loop is event-controlled.

1/12/2007 School of Computer Science [email protected] 156


So, Which Type of Loop Should I
Use?
• Use a for loop for counter-controlled
repetition.
• Use a while or do-while loop for event-
controlled repetition.
– Use a do-while loop when the loop must
execute at least one time.
– Use a while loop when it is possible that the
loop may never execute.

1/12/2007 School of Computer Science [email protected] 157


Infinite Loop

• Infinite Loop: A loop that never ends.


– Generally, you want to avoid these!
– There are special cases, however, when
you do want to create infinite loops on
purpose.
• Common Exam Questions:
– Given a piece of code, identify the bug in
the code.
– You may need to identify infinite loops.

1/12/2007 School of Computer Science [email protected] 158


Infinite Loop Example #1
#include <stdio.h>
#define MAX 10
Index: 1
main ()
Index: 1
{
Index: 1
int index =1;
Index: 1
while (index <= MAX)
{ Index: 1

printf ("Index: %d\n", index);


} …
[forever]
}

1/12/2007 School of Computer Science [email protected] 159


Infinite Loop, Example #2
#include <stdio.h>
Index: 1
/*no MAX here*/
main () Index: 2

{ Index: 3

int index = 1; Index: 4

while (index > 0) Index: 5


{
printf ("Index: %d\n", index); … [forever] ?
index = index + 1;
}
}
1/12/2007 School of Computer Science [email protected] 160
Nested Loops

• Loops may be nested (embedded) inside


of each other.
• Actually, any control structure (sequence,
selection, or repetition) may be nested
inside of any other control structure.
• It is common to see nested for loops.

1/12/2007 School of Computer Science [email protected] 161


Nested for Loops
for ( i = 1; i < 5; i = i + 1 )
{
for ( j = 1; j < 3; j = j + 1 )
{
if ( j % 2 == 0 ) How many times is the “if”
{ statement executed?
printf (“O”) ;
}
What is the output ?
else
{
printf (“X”) ;
}
}
printf (“\n”) ;
}

1/12/2007 School of Computer Science [email protected] 162


The break Statement
• The break statement can be used in
while, do-while, and for loops to
cause premature exit of the loop.

1/12/2007 School of Computer Science [email protected] 163


Example break in a for Loop
#include <stdio.h>
int main ( )
{ OUTPUT:
int i ;
for ( i = 1; i < 10; i = i + 1 ) 1234
{
if (i == 5)
Broke out of loop at i = 5.
{
break ;
}
printf (“%d “, i) ;
}
printf (“\nBroke out of loop at i = %d.\n”, i) ;
return 0 ;
}

1/12/2007 School of Computer Science [email protected] 164


The continue Statement

• The continue statement can be used


in while, do-while, and for loops.
• It causes the remaining statements in
the body of the loop to be skipped for
the current iteration of the loop.

1/12/2007 School of Computer Science [email protected] 165


Example continue in a for Loop
#include <stdio.h>
int main ( )
{ OUTPUT:
int i ;
for ( i = 1; i < 10; i = i + 1 ) 12346789
{
if (i == 5)
Done.
{
continue ;
}
printf (“%d ”, i) ;
}
printf (“\nDone.\n”) ;
return 0 ;
}
1/12/2007 School of Computer Science [email protected] 166
Debugging Tips
• Trace your code by hand (a hand trace),
keeping track of the value of each
variable.
• Insert temporary printf() statements so you
can see what your program is doing.
– Confirm that the correct value(s) has been
read in.
– Check the results of arithmetic computations
immediately after they are performed.

1/12/2007 School of Computer Science [email protected] 167


Multiple Selection

• So far, we have only seen binary


selection. if ( age >= 18 )
if ( age >= 18 )
{
{
printf(“Vote!\n”) ;
printf(“Vote!\n”) ;
}
}
else
{
printf(“Maybe next time!\n”) ;
}

1/12/2007 School of Computer Science [email protected] 168


Multiple Selection (con’t)

• Sometimes it is necessary to branch in


more than two directions.
• We do this via multiple selection.
• The multiple selection mechanism in C is
the switch statement.

1/12/2007 School of Computer Science [email protected] 169


Multiple Selection with if
if (day == 0 ) {
printf (“Sunday”) ; if (day == 4) {
} printf (“Thursday”) ;
}
if (day == 1 ) { if (day == 5) {
printf (“Monday”) ; printf (“Friday”) ;
} }
if (day == 2) { if (day == 6) {
printf (“Tuesday”) ; printf (“Saturday”) ;
}
}
if ((day < 0) || (day > 6)) {
if (day == 3) { printf(“Error - invalid day.\n”) ;
printf (“Wednesday”) ; }
}

1/12/2007 School of Computer Science [email protected] 170


Multiple Selection with if-else
if (day == 0 ) {
printf (“Sunday”) ;
} else if (day == 1 ) {
printf (“Monday”) ;
} else if (day == 2) { This if-else structure is more
printf (“Tuesday”) ;
} else if (day == 3) { efficient than the corresponding
printf (“Wednesday”) ;
} else if (day == 4) {
if structure. Why?
printf (“Thursday”) ;
} else if (day == 5) {
printf (“Friday”) ;
} else if (day = 6) {
printf (“Saturday”) ;
} else {
printf (“Error - invalid day.\n”) ;
}

1/12/2007 School of Computer Science [email protected] 171


The switch Multiple-Selection
Structure
switch ( integer expression )
{
case constant1 :
statement(s)
break ;
case constant2 :
statement(s)
break ;

...
default:
statement(s)
break ;
}

1/12/2007 School of Computer Science [email protected] 172


switch Statement Details
• The last statement of each case in the
switch should almost always be a break.
• The break causes program control to jump
to the closing brace of the switch structure.
• Switch statement can only test for equality
condition (==).
• A switch statement will compile without a
default case, but always consider using one.

1/12/2007 School of Computer Science [email protected] 173


Good Programming Practices

• Include a default case to catch invalid


data.
• Inform the user of the type of error that
has occurred (e.g., “Error - invalid day.”).
• If appropriate, display the invalid value.

1/12/2007 School of Computer Science [email protected] 174


switch Example
switch ( day )
{
case 0: printf (“Sunday\n”) ;
break ;
case 1: printf (“Monday\n”) ; Is this structure more
break ;
case 2: printf (“Tuesday\n”) ; efficient than the
break ;
case 3: printf (“Wednesday\n”) ;
equivalent nested if-else
break ; structure?
case 4: printf (“Thursday\n”) ;
break ;
case 5: printf (“Friday\n”) ;
break ;
case 6: printf (“Saturday\n”) ;
break ;
default: printf (“Error -- invalid day.\n”) ;
break ;
}

1/12/2007 School of Computer Science [email protected] 175


Why Use a switch Statement?

• A nested if-else structure is just as efficient


as a switch statement.
• However, a switch statement may be
easier to read.
• Also, it is easier to add new cases to a
switch statement than to a nested if-else
structure.

1/12/2007 School of Computer Science [email protected] 176


The char Data Type
• The char data type holds a single character.
char ch;
• Example assignments:
char grade, symbol;
grade = ‘B’;
symbol = ‘$’;
• The char is held as a one-byte integer in memory.
The ASCII code is what is actually stored, so we
can use them as characters or integers,
depending on our need.
1/12/2007 School of Computer Science [email protected] 177
The char Data Type (con’t)
• Use
scanf (“%c”, &ch) ;
to read a single character into the variable ch.
(Note that the variable does not have to be called
“ch”.”)
• Use
printf(“%c”, ch) ;
to display the value of a character variable.

1/12/2007 School of Computer Science [email protected] 178


char Example
#include <stdio.h>
int main ( )
{
char ch ;

printf (“Enter a character: “) ;


scanf (“%c”, &ch) ;
printf (“The value of %c is %d.\n”, ch, ch) ;
return 0 ;
}

If the user entered an A, the output would be:


The value of A is 65.
1/12/2007 School of Computer Science [email protected] 179
The getchar ( ) Function
• The getchar( ) function is found in the stdio
library.
• The getchar( ) function reads one character
from stdin (the standard input buffer) and
returns that character’s ASCII value.
• The value can be stored in either a character
variable or an integer variable.

1/12/2007 School of Computer Science [email protected] 180


getchar ( ) Example
#include <stdio.h>
int main ( )
{
char ch ; /* int ch would also work! */

printf (“Enter a character: “) ;


ch = getchar( ) ;
printf (“The value of %c is %d.\n”, ch, ch) ;
return 0 ;
}

If the user entered an A, the output would be:


The value of A is 65.
1/12/2007 School of Computer Science [email protected] 181
Problems with Reading Characters
• When getting characters, whether using scanf( ) or
getchar( ), realize that you are reading only one
character.
• What will the user actually type? The character
he/she wants to enter, followed by pressing ENTER.
• So, the user is actually entering two characters,
his/her response and the newline character.
• Unless you handle this, the newline character will
remain in the stdin stream causing problems the next
time you want to read a character. Another call to
scanf() or getchar( ) will remove it.
1/12/2007 School of Computer Science [email protected] 182
Improved getchar( ) Example
#include <stdio.h>
int main ( )
{
char ch, newline ;

printf (“Enter a character: “) ;


ch = getchar( ) ;
newline = getchar( ) ; /* could also use scanf(“%c”, &newline) ; */
printf (“The value of %c is %d.\n”, ch, ch) ;
return 0 ;
}

If the user entered an A, the output would be:

The value of A is 65.


1/12/2007 School of Computer Science [email protected] 183
Additional Concerns with Garbage in
stdin
• When we were reading integers using scanf( ), we
didn’t seem to have problems with the newline
character, even though the user was typing ENTER
after the integer.
• That is because scanf( ) was looking for the next
integer and ignored the newline (whitespace).
• If we use scanf (“%d”, &num); to get an integer, the
newline is still stuck in the input stream.
• If the next item we want to get is a character, whether
we use scanf( ) or getchar( ), we will get the newline.
• We have to take this into account and remove it.
1/12/2007 School of Computer Science [email protected] 184
EOF Predefined Constant
• getchar( ) is usually used to get characters from
a file until the end of the file is reached.
• The value used to indicate the end of file varies
from system to system. It is system
dependent.
• But, regardless of the system you are using,
there is a #define in the stdio library for a
symbolic integer constant called EOF.
• EOF holds the value of the end-of-file marker for
the system that you are using.

1/12/2007 School of Computer Science [email protected] 185


getchar( ) Example Using EOF
#include <stdio.h>
int main ()
{
int grade, aCount, bCount, cCount, dCount, fCount ;
aCount = bCount = cCount = dCount = fCount = 0 ;
while ( (grade = getchar( ) ) != EOF ) {
switch ( grade ) {
case ‘A’: aCount++; break ;
case ‘B’: bCount++; break ;
case ‘C’ : cCount++; break ;
case ‘D’: dCount++; break ;
case ‘F’: fCount++; break ;
default : break ;
}
}
return 0 ;
}

1/12/2007 School of Computer Science [email protected] 186


Incremental Programming
Review
• Write your code in incomplete but working pieces.
• For example, for your projects,
– Don’t write the whole program at once.
– Just write enough to display the user prompt on
the screen.
– Get that part working first (compile and run).
– Next, write the part that gets the value from the
user, and then just print it out.

1/12/2007 School of Computer Science [email protected] 187


Increment Programming Review
(con’t)
– Get that working (compile and run).
– Next, change the code so that you use the
value in a calculation and print out the
answer.
– Get that working (compile and run).
– Continue this process until you have the final
version.
– Get the final version working.
• Bottom line: Always have a working
version of your program!
1/12/2007 School of Computer Science [email protected] 188
Example of Incremental
Programming
Problem:
• Write an interactive program that allows the
user to calculate the interest accrued on a
savings account. The interest is compounded
annually.
• The user must supply the principal amount,
the interest rate, and the number of years
over which to compute the interest.

1/12/2007 School of Computer Science [email protected] 189


Rough Algorithm
Print explanation of the program
Get <principal> from user
Get <interest rate> from user
Get <number of years> from user
<amount> = <principal>
While (<number of years> > 0 )
amount = amount + (amount X <interest rate>)
<number of years> = <number of year> + 1
End_while
<interest accrued> = <amount> - <principal>
Display report
1/12/2007 School of Computer Science [email protected] 190
Report Design

Interest rate : 7.0000 %


Period : 20 years

Principal at start of period : 1000.00


Interest accrued : 2869.68
Total amount at end of period : 3869.68

1/12/2007 School of Computer Science [email protected] 191


Version #1
/* Filename: interest.c
* Author: Hemant Mehta
* Date written: 11/14//06
* Description: This program computes the interest accrued in an account
* that compounds interest annually. */
#include <stdio.h>
int main ( )
{
/* Print Instructions */
printf (“This program computes the interest accrued in an account that\n”);
printf (“compounds interest annually. You will need to enter the amount\n”);
printf (“of the principal, the interest rate and the number of years.\n\n”);

return 0;
}

1/12/2007 School of Computer Science [email protected] 192


Output #1

This program computes the interest accrued in an account that


compounds interest annually. You will need to enter the amount
of the principal, the interest rate and the number of years.

1/12/2007 School of Computer Science [email protected] 193


Version #2
/* Filename: interest.c
* Author: ___________
* Date written: 11/14//99
* Description: This program computes the interest accrued in an account
* that compounds interest annually. */
#include <stdio.h>
int main ( )
{
float principal, rate ;
int years ;
/* Print Instructions */
printf (“This program computes the interest accrued in an account that\n”) ;
printf (“compounds interest annually. You will need to enter the amount\n”) ;
printf (“of the principal, the interest rate and the number of years.\n\n”) ;
/* Get input from user */
printf (“Enter the principal amount : “) ;
scanf (“%f”, &principal) ;
printf (“Enter the interest rate as a decimal (for 7%% enter .07) : “) ;
scanf (“%f”, &rate) ;
printf (“Enter the number of years : “) ;
scanf (“%d”, &years) ;
printf (“\nprincipal = %f, rate = %f, years = %d\n”, principal, rate, years ) ;
return 0 ;
}

1/12/2007 School of Computer Science [email protected] 194


Output #2
This program computes the interest accrued in an account that
compounds interest annually. You will need to enter the amount
of the principal, the interest rate and the number of years.

Enter the principal amount : 1000.00


Enter the interest rate as a decimal (for 7% enter .07) : .07
Enter the number of years : 20

principal = 1000.000000, rate = 0.070000, years = 20

1/12/2007 School of Computer Science [email protected] 195


Version #3
/* Filename: interest.c
* Author: ____________
* Date written: 11/14//99
* Description: This program computes the interest accrued in an account
* that compounds interest annually. */
#include <stdio.h>
int main ( )
{
float principal, rate, amount, interest ;
int years, i ;
/* Print Instructions */
printf (“This program computes the interest accrued in an account that\n”);
printf (“compounds interest annually. You will need to enter the amount\n”);
printf (“of the principal, the interest rate and the number of years.\n\n”);
/* Get input from user */
printf (“Enter the principal amount : “);
scanf (“%f”, &principal);
printf (“Enter the interest rate as a decimal (for 7%% enter .07) : “) ;
scanf (“%f”, &rate);
printf (“Enter the number of years : “);
scanf (“%d”, &years);

1/12/2007 School of Computer Science [email protected] 196


Version #3 (con’t)
/* Save the original principal amount by varying another variable, amount */
amount = principal;
/* Calculate total amount in the account after the specified number of years */
for ( i = 0 ; i < 1 ; i++ )
{
amount += amount * rate ;
}
/* Calculate accrued interest */
interest = amount - principal ;

printf (“\nprincipal = %f, rate = %f, years = %d\n”, principal, rate, years ) ;
printf (“amount = %f, interest = %f\n”);

return 0 ;
}

1/12/2007 School of Computer Science [email protected] 197


Output #3
This program computes the interest accrued in an account that
compounds interest annually. You will need to enter the amount
of the principal, the interest rate and the number of years.

Enter the principal amount : 1000.00


Enter the interest rate as a decimal (for 7% enter .07) : .07
Enter the number of years : 20

principal = 1000.000000, rate = 0.070000, years = 20


amount = 1070.000000, interest = 70.000000

1/12/2007 School of Computer Science [email protected] 198


Version #4
/* Filename: interest.c
* Author: ____________
* Date written: 11/14//99
* Description: This program computes the interest accrued in an account
* that compounds interest annually. */
#include <stdio.h>
int main ( )
{
float principal, rate, amount, interest ;
int years, i ;
/* Print Instructions */
printf (“This program computes the interest accrued in an account that\n”);
printf (“compounds interest annually. You will need to enter the amount\n”);
printf (“of the principal, the interest rate and the number of years.\n\n”);
/* Get input from user */
printf (“Enter the principal amount : “);
scanf (“%f”, &principal);
printf (“Enter the interest rate as a decimal (for 7%% enter .07) : “) ;
scanf (“%f”, &rate);
printf (“Enter the number of years : “);
scanf (“%d”, &years);

1/12/2007 School of Computer Science [email protected] 199


Version #4 (con’t)
/* Save the original principal amount by varying another variable, amount */
amount = principal;
/* Calculate total amount in the account after the specified number of years */
for ( i = 0 ; i < 2 ; i++ )
{
amount += amount * rate ;
}
/* Calculate accrued interest */
interest = amount - principal ;

printf (“\nprincipal = %f, rate = %f, years = %d\n”, principal, rate, years ) ;
printf (“amount = %f, interest = %f\n”);

return 0 ;
}

1/12/2007 School of Computer Science [email protected] 200


Output #4
This program computes the interest accrued in an account that
compounds interest annually. You will need to enter the amount
of the principal, the interest rate and the number of years.

Enter the principal amount : 1000.00


Enter the interest rate as a decimal (for 7% enter .07) : .07
Enter the number of years : 20

principal = 1000.000000, rate = 0.070000, years = 20


amount = 1144.900000, interest = 144.900000

1/12/2007 School of Computer Science [email protected] 201


Version #5
/* Filename: interest.c
* Author: ____________
* Date written: 11/14//99
* Description: This program computes the interest accrued in an account
* that compounds interest annually. */
#include <stdio.h>
int main ( )
{
float principal, rate, amount, interest ;
int years, i ;
/* Print Instructions */
printf (“This program computes the interest accrued in an account that\n”);
printf (“compounds interest annually. You will need to enter the amount\n”);
printf (“of the principal, the interest rate and the number of years.\n\n”);
/* Get input from user */
printf (“Enter the principal amount : “);
scanf (“%f”, &principal);
printf (“Enter the interest rate as a decimal (for 7%% enter .07) : “) ;
scanf (“%f”, &rate);
printf (“Enter the number of years : “);
scanf (“%d”, &years);

1/12/2007 School of Computer Science [email protected] 202


Version #5 (con’t)
/* Save the original principal amount by varying another variable, amount */
amount = principal;
/* Calculate total amount in the account after the specified number of years */
for ( i = 0 ; i < years ; i++ )
{
amount += amount * rate ;
}
/* Calculate accrued interest */
interest = amount - principal ;

printf (“\nprincipal = %f, rate = %f, years = %d\n”, principal, rate, years ) ;
printf (“amount = %f, interest = %f\n”);

return 0 ;
}

1/12/2007 School of Computer Science [email protected] 203


Output #5
This program computes the interest accrued in an account that
compounds interest annually. You will need to enter the amount
of the principal, the interest rate and the number of years.

Enter the principal amount : 1000.00


Enter the interest rate as a decimal (for 7% enter .07) : .07
Enter the number of years : 20

principal = 1000.000000, rate = 0.070000, years = 20


amount = 3869.680000, interest = 2869.680000

1/12/2007 School of Computer Science [email protected] 204


Final Version
/* Filename: interest.c
* Author: ____________
* Date written: 11/14//99
* Description: This program computes the interest accrued in an account
* that compounds interest annually. */
#include <stdio.h>
int main ( )
{
float principal, rate, amount, interest ;
int years, i ;
/* Print Instructions */
printf (“This program computes the interest accrued in an account that\n”);
printf (“compounds interest annually. You will need to enter the amount\n”);
printf (“of the principal, the interest rate and the number of years.\n\n”);
/* Get input from user */
printf (“Enter the principal amount : “);
scanf (“%f”, &principal);
printf (“Enter the interest rate as a decimal (for 7%% enter .07) : “) ;
scanf (“%f”, &rate);
printf (“Enter the number of years : “);
scanf (“%d”, &years);

1/12/2007 School of Computer Science [email protected] 205


Final Version (con’t)
/* Save the original principal amount by varying another variable, amount */
amount = principal;
/* Calculate total amount in the account after the specified number of years */
for ( i = 0 ; i < years ; i++ )
{
amount += amount * rate ;
}
/* Calculate accrued interest */
interest = amount - principal ;
/* Print report */
printf (“Interest rate : %.4f %%\n”, 100 * rate ) ;
printf (“ Period : %d years\n\n”, years ) ;
printf (“ Principal at start of period : %9.2f”, principal );
printf (“ Interest accrued : %9.2f”, interest );
printf (“Total amount at end of period : %9.2f”, amount);

return 0 ;
}

1/12/2007 School of Computer Science [email protected] 206


Final Output
This program computes the interest accrued in an account that
compounds interest annually. You will need to enter the amount
of the principal, the interest rate and the number of years.

Enter the principal amount : 1000.00


Enter the interest rate as a decimal (for 7% enter .07) : .07
Enter the number of years : 20

Interest rate : 7.0000 %


Period : 20 years

Principal at start of period : 1000.00


Interest accrued : 2869.68
Total amount at end of period : 3869.68

1/12/2007 School of Computer Science [email protected] 207


Top-Down Design
• If we look at a problem as a whole, it may seem
impossible to solve because it is so complex.
Examples:
– writing a tax computation program
– writing a word processor
• Complex problems can be solved using top-
down design, also known as stepwise
refinement, where
– We break the problem into parts
– Then break the parts into parts
– Soon, each of the parts will be easy to do
1/12/2007 School of Computer Science [email protected] 208
Advantages of Top-Down
Design
• Breaking the problem into parts helps us to
clarify what needs to be done.
• At each step of refinement, the new parts
become less complicated and, therefore,
easier to figure out.
• Parts of the solution may turn out to be
reusable.
• Breaking the problem into parts allows more
than one person to work on the solution.

1/12/2007 School of Computer Science [email protected] 209


An Example of Top-Down
Design
• Problem:
– We own a home improvement company.
– We do painting, roofing, and basement
waterproofing.
– A section of town has recently flooded
(zip code 21222).
– We want to send out pamphlets to our
customers in that area.

1/12/2007 School of Computer Science [email protected] 210


The Top Level
• Get the customer list from a file.
• Sort the list according to zip code.
• Make a new file of only the customers with the zip
code 21222 from the sorted customer list.
• Print an envelope for each of these customers.

Main

Read Sort Select Print

1/12/2007 School of Computer Science [email protected] 211


Another Level?
• Should any of these steps be broken down
further? Possibly.
• How do I know? Ask yourself whether or
not you could easily write the algorithm for
the step. If not, break it down again.
• When you are comfortable with the
breakdown, write the pseudocode for each
of the steps (modules) in the hierarchy.
• Typically, each module will be coded as a
separate function.
1/12/2007 School of Computer Science [email protected] 212
Structured Programs
• We will use top-down design for all remaining
programming projects.
• This is the standard way of writing programs.
• Programs produced using this method and using
only the three kinds of control structures,
sequential, selection and repetition, are called
structured programs.
• Structured programs are easier to test, modify,
and are also easier for other programmers to
understand.

1/12/2007 School of Computer Science [email protected] 213


Another Example

• Problem: Write a program that draws this


picture of a house.

1/12/2007 School of Computer Science [email protected] 214


The Top Level
• Draw the outline of the house
• Draw the chimney
• Draw the door
• Draw the windows

Main

Draw Draw Draw Draw


Outline Chimney Door Windows

1/12/2007 School of Computer Science [email protected] 215


Pseudocode for Main

Call Draw Outline


Call Draw Chimney
Call Draw Door
Call Draw Windows

1/12/2007 School of Computer Science [email protected] 216


Observation
• The door has both a frame and knob. We
could break this into two steps.
Main

Draw Draw Draw Draw


Outline Chimney Door Windows

Draw Draw
Door Frame Knob

1/12/2007 School of Computer Science [email protected] 217


Pseudocode for Draw Door

Call Draw Door Frame


Call Draw Knob

1/12/2007 School of Computer Science [email protected] 218


Another Observation

• There are three windows to be drawn.

Main

Draw Draw
Outline . . . Windows

Draw Draw Draw


Window 1 Window 2 Window 3

1/12/2007 School of Computer Science [email protected] 219


One Last Observation
• But don’t the windows look the same?
They just have different locations.
• So, we can reuse the code that draws a
window.
– Simply copy the code three times and edit it to
place the window in the correct location, or
– Use the code three times, “sending it” the
correct location each time (we will see how to
do this later).
• This is an example of code reuse.
1/12/2007 School of Computer Science [email protected] 220
Reusing the Window Code

Main

Draw Draw
Outline . . . Windows

Draw a
Window

1/12/2007 School of Computer Science [email protected] 221


Pseudocode for Draw Windows

Call Draw a Window, sending in Location 1


Call Draw a Window, sending in Location 2
Call Draw a Window, sending in Location 3

1/12/2007 School of Computer Science [email protected] 222


Review of Structured
Programming
• Structured programming is a problem solving
strategy and a programming methodology that
includes the following guidelines:
– The program uses only the sequence,
selection, and repetition control structures.
– The flow of control in the program should be
as simple as possible.
– The construction of a program embodies top-
down design.

1/12/2007 School of Computer Science [email protected] 223


Review of Top-Down Design
• Involves repeatedly decomposing a
problem into smaller problems
• Eventually leads to a collection of small
problems or tasks each of which can be
easily coded
• The function construct in C is used to
write code for these small, simple
problems.

1/12/2007 School of Computer Science [email protected] 224


Functions
• A C program is made up of one or more functions,
one of which is main( ).
• Execution always begins with main( ), no matter
where it is placed in the program. By convention,
main( ) is located before all other functions.
• When program control encounters a function
name, the function is called (invoked).
– Program control passes to the function.
– The function is executed.
– Control is passed back to the calling function.

1/12/2007 School of Computer Science [email protected] 225


Sample Function Call
#include <stdio.h>

int main ( ) printf is the name of a predefined


{ function in the stdio library

printf (“Hello World!\n”) ; this statement is


return 0 ; is known as a
} function call
this is a string we are passing
as an argument (parameter) to
the printf function

1/12/2007 School of Computer Science [email protected] 226


Functions (con’t)
• We have used few predefined functions such
as:
– printf
– scanf
– getchar
• Programmers can write their own functions.
• Typically, each module in a program’s design
hierarchy chart is implemented as a function.
• C function names follow the same naming rules
as C variables.
1/12/2007 School of Computer Science [email protected] 227
Sample Programmer-Defined
#include <stdio.h>
Function
void printMessage ( void ) ;

int main ( )
{
printMessage ( ) ;
return 0 ;
}

void printMessage ( void )


{
printf (“A message for you:\n\n”) ;
printf (“Have a nice day!\n”) ;
}

1/12/2007 School of Computer Science [email protected] 228


Examining printMessage
#include <stdio.h>

void printMessage ( void ) ; function prototype

int main ( )
{
printMessage ( ) ; function call
return 0 ;
}

void printMessage ( void ) function header


{
printf (“A message for you:\n\n”) ; function
printf (“Have a nice day!\n”) ; body
}

function definition
1/12/2007 School of Computer Science [email protected] 229
The Function Prototype
• Informs the compiler that there will be a function
defined later that:
returns this type
has this name
takes these arguments

void printMessage (void) ;

• Needed because the function call is made before


the definition -- the compiler uses it to see if the
call is made properly
1/12/2007 School of Computer Science [email protected] 230
The Function Call
• Passes program control to the function
• Must match the prototype in name, number of
arguments, and types of arguments
void printMessage (void) ;
int main ( ) same name no arguments
{
printMessage ( ) ;
return 0 ;
}
1/12/2007 School of Computer Science [email protected] 231
The Function Definition
• Control is passed to the function by the function
call. The statements within the function body will
then be executed.
void printMessage ( void )
{
printf (“A message for you:\n\n”) ;
printf (“Have a nice day!\n”) ;
}

• After the statements in the function have


completed, control is passed back to the calling
function, in this case main( ) . Note that the
calling function does not have to be main( ) .
1/12/2007 School of Computer Science [email protected] 232
General Function Definition
Syntax
type functionName ( parameter1, . . . , parametern )
{
variable declaration(s)
statement(s)
}
If there are no parameters, either
functionName( ) OR functionName(void)
is acceptable.
• There may be no variable declarations.
• If the function type (return type) is void, a return
statement is not required, but the following are permitted:
return ; OR return( ) ;
1/12/2007 School of Computer Science [email protected] 233
Using Input Parameters
void printMessage (int counter) ;
int main ( )
{
int num;
printf (“Enter an integer: “) ;
scanf (“%d”, &num) ;
printMessage (num) ; one argument matches the one formal parameter
return 0 ; of type int of type int
}

void printMessage (int counter)


{
int i ;
for ( i = 0; i < counter; i++ )
{
printf (“Have a nice day!\n”) ;
}
}
1/12/2007 School of Computer Science [email protected] 234
Final “Clean” C Code
#include <stdio.h>

void printMessage (int counter) ;

int main ( )
{
int num ; /* number of times to print message */

printf (“Enter an integer: “) ;


scanf (“%d”, &num) ;
printMessage (num) ;

return 0 ;
}

1/12/2007 School of Computer Science [email protected] 235


Final “Clean” C Code (con’t)
/*************************************************************************
** printMessage - prints a message a specified number of times
** Inputs: counter - the number of times the message will be
** printed
** Outputs: None
/*************************************************************************/
void printMessage ( int counter )
{
int i ; /* loop counter */

for ( i = 0; i < counter; i++ )


{
printf (“Have a nice day!\n”) ;
}
}

1/12/2007 School of Computer Science [email protected] 236


Good Programming Practice
• Notice the function header comment before the
definition of function printMessage.
• Your header comments should be neatly formatted
and contain the following information:
– function name
– function description (what it does)
– a list of any input parameters and their meanings
– a list of any output parameters and their meanings
– a description of any special conditions

1/12/2007 School of Computer Science [email protected] 237


Functions Can Return Values
/****************************************************************************
** averageTwo - calculates and returns the average of two numbers
** Inputs: num1 - an integer value
** num2 - an integer value
** Outputs: the floating point average of num1 and num2
*****************************************************************************/
float averageTwo (int num1, int num2)
{
float average ; /* average of the two numbers */

average = (num1 + num2) / 2.0 ;


return average ;
}

1/12/2007 School of Computer Science [email protected] 238


Using averageTwo
#include <stdio.h>
float averageTwo (int num1, int num2) ;
int main ( )
{
float ave ;
int value1 = 5, value2 = 8 ;
ave = averageTwo (value1, value2) ;
printf (“The average of %d and %d is %f\n”, value1, value2, ave) ;
return 0 ;
}

float averageTwo (int num1, int num2)


{
float average ;

average = (num1 + num2) / 2.0 ;


return average ;
}
1/12/2007 School of Computer Science [email protected] 239
Parameter Passing
• Actual parameters are the parameters that
appear in the function call.
average = averageTwo (value1, value2) ;

• Formal parameters are the parameters that


appear in the function header.
float averageTwo (int num1, int num2)

• Actual and formal parameters are matched by


position. Each formal parameter receives the
value of its corresponding actual parameter.
1/12/2007 School of Computer Science [email protected] 240
Parameter Passing (con’t)

• Corresponding actual and formal


parameters do not have to have the same
name, but they may.
• Corresponding actual and formal
parameters must be of the same data
type, with some exceptions.

1/12/2007 School of Computer Science [email protected] 241


Local Variables
• Functions only “see” (have access to) their own
local variables. This includes main( ) .
• Formal parameters are declarations of local
variables. The values passed are assigned to
those variables.
• Other local variables can be declared within the
function body.

1/12/2007 School of Computer Science [email protected] 242


Parameter Passing and Local
Variables
#include <stdio.h> float averageTwo (int num1, int num2)
float averageTwo (int num1, int num2) ; {
int main ( ) float average ;
{
float ave ; average = (num1 + num2) / 2.0 ;
int value1 = 5, value2 = 8 ; return average ;
}
ave = averageTwo (value1, value2) ;
printf (“The average of “) ;
printf (“%d and %d is %f\n”,
value1, value2, ave) ;
return 0 ;
}
value1 value2 ave num1 num2 average

5 8

int int float int int float


1/12/2007 School of Computer Science [email protected] 243
Same Name, Still Different Memory
Locations
#include <stdio.h> float averageTwo (int num1, int num2)
float averageTwo (int num1, int num2) ; {
int main ( ) float average ;
{
float average ; average = (num1 + num2) / 2.0 ;
int num1 = 5, num2 = 8 ; return average ;
}
average = averageTwo (num1,
num2) ;
printf (“The average of “) ;
printf (“%d and %d is %f\n”,
num1, num2, average) ;
return 0 ;
}
num1 num2 average num1 num2 average

5 8
int int float int int float
1/12/2007 School of Computer Science [email protected] 244
Changes to Local Variables Do NOT
Change Other Variables with the
#include <stdio.h> Same Name
void addOne (int number) ; void addOne (int num1)
{
int main ( ) num1++ ;
{ printf (“In addOne: “) ;
int num1 = 5 ; printf (“num1 = %d\n”, num1) ;
addOne (num1) ; }
printf (“In main: “) ;
printf (“num1 = %d\n”, num1) ; num1
return 0 ;
} int
num1
5 OUTPUT
int In addOne: num1 = 6
In main: num1 = 5
1/12/2007 School of Computer Science [email protected] 245
Call by Value and Call by Reference
By Default the function calling is by Value i.e. there is no
relation between actual and formal parameter. Change in
formal parameter doesn't affect actual parameter.

In case if we require the value updated by a function, there


is a provision for single updated value by using return
type of the function. But in case we require more than
one value the we must call the function by reference.

In case of call by reference we use pointers.

1/12/2007 School of Computer Science [email protected] 246


Header Files
• Header files contain function prototypes
for all of the functions found in the
specified library.
• They also contain definitions of constants
and data types used in that library.

1/12/2007 School of Computer Science [email protected] 247


Commonly Used Header Files
Header File Contains Function Prototypes for:
<stdio.h> standard input/output library functions
and information used by them
<math.h> math library functions
<stdlib.h> conversion of numbers to text, text to
numbers, memory allocation, random
numbers, and other utility functions
<time.h> manipulating the time and date
<ctype.h> functions that test characters for certain
properties and that can convert case
<string.h> functions that manipulate character strings

1/12/2007 School of Computer Science [email protected] 248


Using Header Files
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main ( )
{
float side1, side2, hypotenuse ;
printf(“Enter the lengths of the right triangle sides: “) ;
scanf(“%f%f”, &side1, &side2) ;
if ( (side1 <= 0) || (side2 <= 0) {
exit (1) ;
}
hypotenuse = sqrt ( (side1 * side1) + (side2 * side2) ) ;
printf(“The hypotenuse = %f\n”, hypotenuse) ;
return 0 ;
}
1/12/2007 School of Computer Science [email protected] 249
User Defined Header Files
Save different functions in a file (extension .h). This file can
be used as header file. e.g. myheader.h

In order to include the this user defined header file we can


• Either put the file in the include folder.
• Or keep it in the current folder an include it with
#include “myheader.h”

1/12/2007 School of Computer Science [email protected] 250


The stack and the heap

• Local variables, function arguments, return value


are stored on a stack
• Each function call generates a new "stack frame"
• After function returns, stack frame disappears
– along with all local variables and function
arguments for that invocation

1/12/2007 School of Computer Science [email protected] 251


The stack and the heap

void contrived_example(int i, float f)


{
int j = 10;
double d = 3.14;
int arr[10];
/* do some stuff, then return */
return (j + i);
}
1/12/2007 School of Computer Science [email protected] 252
The stack and the heap

/* somewhere in code */
int k = contrived_example(42, 3.3);
• What does this look like on the stack?

1/12/2007 School of Computer Science [email protected] 253


The stack and the heap

(more frames)
return value 52
function i = 42
arguments f = 3.3
j = 10 stack frame
local d = 3.14
variables
arr[10] =
<garbage>

1/12/2007 School of Computer Science [email protected] 254


The stack and the heap

• Another example:
int factorial(int i)
{
if (i == 0) {
return 1;
} else {
return i * factorial (i - 1);
}
}

1/12/2007 School of Computer Science [email protected] 255


The stack and the heap

• Pop quiz: what goes on the stack for


factorial(3)?
• For each stack frame, have...
– no local variables
– one argument (i)
– one return value
• Each recursive call generates a new stack frame
– which disappears after the call is complete

1/12/2007 School of Computer Science [email protected] 256


The stack and the heap

return value ?
factorial(3) stack frame
i = 3

1/12/2007 School of Computer Science [email protected] 257


The stack and the heap

return value ?
factorial(2) stack frame
i = 2
return value ?
factorial(3) stack frame
i = 3

1/12/2007 School of Computer Science [email protected] 258


The stack and the heap

return value ?
factorial(1) stack frame
i = 1
return value ?
factorial(2) stack frame
i = 2
return value ?
factorial(3) stack frame
i = 3

1/12/2007 School of Computer Science [email protected] 259


The stack and the heap

return value ?
factorial(0) stack frame
i = 0
return value ?
factorial(1) stack frame
i = 1
return value ?
factorial(2) stack frame
i = 2
return value ?
factorial(3) stack frame
i = 3

1/12/2007 School of Computer Science [email protected] 260


The stack and the heap

return value 1
factorial(0) stack frame
i = 0
return value ?
factorial(1) stack frame
i = 1
return value ?
factorial(2) stack frame
i = 2
return value ?
factorial(3) stack frame
i = 3

1/12/2007 School of Computer Science [email protected] 261


The stack and the heap

return value 1
factorial(1) stack frame
i = 1
return value ?
factorial(2) stack frame
i = 2
return value ?
factorial(3) stack frame
i = 3

1/12/2007 School of Computer Science [email protected] 262


The stack and the heap

return value 2
factorial(2) stack frame
i = 2
return value ?
factorial(3) stack frame
i = 3

1/12/2007 School of Computer Science [email protected] 263


The stack and the heap

return value 6
factorial(3) stack frame
i = 3

1/12/2007 School of Computer Science [email protected] 264


The stack and the heap

factorial(3)

result: 6

1/12/2007 School of Computer Science [email protected] 265


The stack and the heap

void foo() {
int arr[10]; /* local (on stack) */
/* do something with arr */
} /* arr is deallocated */
• Local variables sometimes called "automatic"
variables; deallocation is automatic

1/12/2007 School of Computer Science [email protected] 266


The stack and the heap

foo

local arr[10] =
stack frame
variables <whatever>

1/12/2007 School of Computer Science [email protected] 267


The stack and the heap

• The "heap" is the general pool of computer


memory
• Memory is allocated on the heap using
malloc() or calloc()
• Heap memory must be explicitly freed using
free()
• Failure to do so  memory leak!

1/12/2007 School of Computer Science [email protected] 268


The stack and the heap

void foo2() {
int *arr;
/* allocate memory on the heap: */
arr = (int *)calloc(10, sizeof(int));
/* do something with arr */
} /* arr is NOT deallocated */

1/12/2007 School of Computer Science [email protected] 269


The stack and the heap

void foo3() {
int *arr;
/* allocate memory on the heap: */
arr = (int *)calloc(10, sizeof(int));
/* do something with arr */
free(arr);
}

1/12/2007 School of Computer Science [email protected] 270


The stack and the heap
0x1234
arr[0]
arr[1]
arr[2]
arr[3]
foo2 and arr[4]
foo3
(etc.)

heap
local arr =
stack frame
variables 0x1234
stack
1/12/2007 School of Computer Science [email protected] 271
The stack and the heap
0x1234
arr[0]
arr[1]
(after foo2
exits, arr[2]
without arr[3]
freeing memory
leak arr[4]
memory)
(etc.)

heap

stack
1/12/2007 School of Computer Science [email protected] 272
The stack and the heap

0x1234 arr[0]
arr[1]
(after foo3
exits, with arr[2]
freeing arr[3]
memory) arr[4]
(etc.)

heap

stack

1/12/2007 School of Computer Science [email protected] 273


1/12/2007 School of Computer Science [email protected] 274
Recursion
• Recursion is a fundamental programming
technique that can provide an elegant solution
certain kinds of problems

[email protected] 1
Recursive Thinking
• A recursive definition is one which uses the word
or concept being defined in the definition itself

• When defining an English word, a recursive


definition is often not helpful

• But in other situations, a recursive definition can


be an appropriate way to express a concept

• Before applying recursion to programming, it is


best to practice thinking recursively

[email protected] 2
Recursive Definitions
• Consider the following list of numbers:

24, 88, 40, 37

• Such a list can be defined as follows:

A LIST is a: number
or a: number comma LIST

• That is, a LIST is defined to be a single number, or


a number followed by a comma followed by a LIST

• The concept of a LIST is used to define itself

[email protected] 3
Recursive Definitions
• The recursive part of the LIST definition is
used several times, terminating with the
non-recursive part:
number comma LIST
24 , 88, 40, 37

number comma LIST


88 , 40, 37

number comma LIST


40 , 37

number
37

[email protected] 4
Infinite Recursion
• All recursive definitions have to have a non-
recursive part

• If they didn't, there would be no way to terminate


the recursive path

• Such a definition would cause infinite recursion

• This problem is similar to an infinite loop, but the


non-terminating "loop" is part of the definition
itself

• The non-recursive part is often called the base


case

[email protected] 5
Recursive Definitions
• N!, for any positive integer N, is defined to be the
product of all integers between 1 and N inclusive

• This definition can be expressed recursively as:


1! = 1
N! = N * (N-1)!

• A factorial is defined in terms of another factorial

• Eventually, the base case of 1! is reached

[email protected] 6
Recursive Definitions

5!
120
5 * 4!
24
4 * 3!
6
3 * 2!
2
2 * 1!
1

[email protected] 7
Recursive Programming
• A Function can invoke itself; if set up that way, it
is called a recursive function

• The code of a recursive function must be


structured to handle both the base case and the
recursive case

• As with any function call, when the function


completes, control returns to the function that
invoked it (which may be an earlier invocation of
itself)

[email protected] 8
Recursive Programming
• Consider the problem of computing the sum of all
the numbers between 1 and any positive integer N

• This problem can be recursively defined as:

N N −1 N −2

∑i
i =1
= N + ∑i
i =1
= N + N −1 + ∑i
i =1
N −3
= N + N −1 + N − 2 + ∑i
i =1
o

[email protected] 9
Recursive Programming
// This function returns the sum of 1 to num
int sum (int num)
{
int result;

if (num == 1)
result = 1;
else
result = num + sum (n-1);

return result;
}

[email protected] 10
Recursive Programming
result = 6
main
sum(3)

result = 3
sum
sum(2)

result = 1
sum
sum(1)

sum

[email protected] 11
Recursive Programming
• Note that just because we can use recursion to
solve a problem, doesn't mean we should

• For instance, we usually would not use recursion


to solve the sum of 1 to N problem, because the
iterative version is easier to understand

• However, for some problems, recursion provides


an elegant solution, often cleaner than an iterative
version

• You must carefully decide whether recursion is the


correct technique for any problem

[email protected] 12
Indirect Recursion
• A function invoking itself is considered to be
direct recursion

• A function could invoke another function, which


invokes another, etc., until eventually the original
function is invoked again
• For example, function m1 could invoke m2, which
invokes m3, which in turn invokes m1 again

• This is called indirect recursion, and requires all


the same care as direct recursion

• It is often more difficult to trace and debug

[email protected] 13
Indirect Recursion

m1 m2 m3

m1 m2 m3

m1 m2 m3

[email protected] 14
Towers of Hanoi
• The Towers of Hanoi is a puzzle made up of three
vertical pegs and several disks that slide on the
pegs

• The disks are of varying size, initially placed on


one peg with the largest disk on the bottom with
increasingly smaller ones on top

• The goal is to move all of the disks from one peg


to another under the following rules:
 We can move only one disk at a time

 We cannot move a larger disk on top of a smaller one

[email protected] 15
Towers of Hanoi

Original Configuration Move 1

Move 2 Move 3

[email protected] 16
Towers of Hanoi

Move 4 Move 5

Move 6 Move 7 (done)

[email protected] 17
Towers of Hanoi
• An iterative solution to the Towers of Hanoi is
quite complex

• A recursive solution is much shorter and more


elegant

[email protected] 18
Towers of Hanoi
#include <stdio.h>
#include <conio.h>

void transfer(int,char,char,char);

int main()
{
int n;
printf("Recursive Solution to Towe of Hanoi Problem\n");
printf("enter the number of Disks");
scanf("%d",&n);
transfer(n,'L','R','C');
getch();
return 0;
}
void transfer(int n,char from,char to,char temp)
{
if (n>0)
{
transfer(n-1,from,temp,to); /* Move n-1 disk from origin to temporary */
printf("Move Disk %d from %c to %c\n",n,from,to);
transfer(n-1,temp,to,from); /* Move n-1 disk from temporary to origin */
}
return;
}
[email protected] 19
Drawbacks of Recursion
Regardless of the algorithm used, recursion has two
important drawbacks:
 Function-Call Overhead

 Memory-Management Issues

[email protected] 20
Eliminating Recursion — Tail
Recursion
A special kind of recursion is tail recursion.
 Tail recursion is when a recursive call is the last thing a
function does.
Tail recursion is important because it makes the
recursion → iteration conversion very easy.
 That is, we like tail recursion because it is easy to
eliminate.
 In fact, tail recursion is such an obvious thing to optimize
that some compilers automatically convert it to iteration.

[email protected] 21
Eliminating Recursion — Tail
Recursion
For a void function, tail recursion looks like this:

void foo(TTT a, UUU b)


{

foo(x, y);
}

For a function returning a value, tail recursion looks like this:

SSS bar(TTT a, UUU b)


{

return bar(x, y);
}

[email protected] 22
A tail-recursive Factorial Function
We will use an auxiliary function to rewrite factorial as tail-
recursive:

int factAux (int x, int result)


{
if (x==0) return result;
return factAux(x-1, result * x);
}
int tailRecursiveFact( int x)
{
return factAux (n, 1);
}

[email protected] 23
Devi Ahilya Vishwavidyalaya

Programming With C
[email protected]

School of Computer Science [email protected]


Devi Ahilya Vishwavidyalaya

Arrays

A sequential collection

School of Computer Science [email protected]


DAVV
SCS

Arrays
 An array is a collection of variables of the same type that are referred to
through a common name.
 A specific element in an array is accessed by an index. In C, all arrays
consist of contiguous memory locations.
 The lowest address corresponds to the first element and the highest
address to the last element.
 Arrays can have from one to several dimensions.

3 [email protected]
DAVV
SCS

Single-Dimensional Arrays
 Generic declaration:
typename variablename[size]
typename is any type
variablename is any legal variable name
size is a constant number
 To define an array of ints with subscripts ranging from 0 to 9, use:
int a[10];

a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]

4 [email protected]
DAVV
SCS

Single-Dimensional Arrays
 Array declared using int a[10]; requires 10*sizeof(int) bytes of
memory
 To access individual array elements, use indexing: a[0]=10; x=a[2];
a[3]=a[2]; a[i]=a[i+1]+10; etc.
 To read a value into an array location, use scanf("%d",&a[3]);
 Accessing an individual array element is a fast operation

5 [email protected]
DAVV
SCS

How Array Indexing Works


 Array elements are stored contiguously (that is, in adjacent memory
locations)
 Address of the kth array element is the start address of the array (that is,
the address of the element at location 0) plus k * sizeof(each individual
array element)
 Example: Suppose we have int a[10]; where a begins at address 6000
in memory. Then a[5] begins at address 6000 + 5*sizeof(int)

6 [email protected]
DAVV
SCS

Using Constants to Define Arrays


 It is useful to define arrays using constants:
#define MONTHS 12
int array [MONTHS];
 However, in ANSI C, you cannot use:
int n;
scanf(“%d”, &n);
int array[n];
 GNU C allows variable length arrays – non-standard

7 [email protected]
DAVV
SCS

Array-Bounds Checking
 C, unlike many languages, DOES NOT check array bounds subscripts
during:
 Compilation
 Runtime
 Programmer must take responsibility for ensuring that array indices are
within the declared bounds

8 [email protected]
DAVV
SCS

Array-Bounds Checking
 If you access beyond the end of an array:
 C calculates the address as usual
 Attempts to treat the location as part of the array
 Program may continue to run,OR may crash with a memory
access violation error (segmentation fault, core dump error)
 It’s better if the program crashes right away – easier to debug

9 [email protected]
DAVV
SCS

Initializing Arrays
 Initialization of arrays can be done by a comma separated list following
its definition.
 Example: int array [4] = { 100, 200, 300, 400 };
is equivalent to:
int array [4];
array[0] = 100;
array[1] = 200;
array[2] = 300;
array[3] = 400;
 Or, you can let the compiler compute the array size: int array[ ] = { 100, 200,
300, 400};

10 [email protected]
DAVV
SCS

Example
#include <stdio.h>
int main( ) {
float expenses[12]={10.3, 9, 7.5, 4.3, 10.5, 7.5, 7.5, 8, 9.9,
10.2, 11.5, 7.8};
int count,month;
float total;
for (month=0, total=0.0; month < 12; month++)
{
total+=expenses[month];
}
for (count=0; count < 12; count++)
printf ("Month %d = %.2f \n", count+1, expenses[count]);
printf("Total = %.2f, Average = %.2f\n", total, total/12);
return 0;
}

11 [email protected]
DAVV
SCS

Multidimensional Arrays
 Arrays in C can have virtually as many dimensions as you want unlike
coordinate geometry.
 Definition is accomplished by adding additional subscripts:
int a [4] [3] ;
 defines a two dimensional array with 4 rows and 3 columns
 a can be thought of as a 1-dimensional array of 4 elements, where
each element is of type int[3]

12 [email protected]
DAVV
SCS

Multidimensional Arrays

The array declared using a[0] a[0][0] a[0][1] a[0][2]

int a [4] [3];


a[1] a[1][0] a[1][1] a[1][2]
is normally thought of as a
table.
a[2] a[2][0] a[2][1] a[2][2]

a[3] a[3][0] a[3][1] a[3][2]

13 [email protected]
DAVV
SCS

Multidimensional Arrays

In memory, which is one-dimensional, the rows


of the array are actually stored contiguously.

increasing order of memory address

a[0][0] a[0][1] a[0][2]

a[0] a[1] a[2] a[3]

14 [email protected]
DAVV
SCS

Initializing Multidimensional Arrays


 Two ways to initialize a[4][3]:
int a[4] [3] = { {1, 2, 3} , { 4, 5, 6} , {7, 8, 9} , {10, 11, 12} };
int a[4] [3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
 These methods are equivalent to:
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1][0] = 4;
...
a[3][2] = 12;

15 [email protected]
DAVV
SCS

#include <stdio.h>
#include <stdlib.h> Example
int main () {
int random1[8][8]; The function
int a, b; int rand( );
for (a = 0; a < 8; a++)
from <stdlib.h>
for (b = 0; b < 8; b++)
returns a random
random1[a][b] = rand( )%2;
int between 0 and
for (a = 0; a < 8; a++)
RAND_MAX, a
{ constant defined
for (b = 0; b < 8; b++) in the same
printf ("%c " , random1[a][b] ? 'x' : 'o'); library.
printf("\n");
}
return 0;
}

16 [email protected]
DAVV
SCS

The Value of the Array Name

#include <stdio.h>  When the array name is used


alone, its value is the address of
int main(){ the array (a pointer to its first
int a[3] = { 1, 2, 3 }; element)
printf( “%d\n”, a[0]);  &a has no meaning if used in
this program
scanf( “%d”, &a[0] );
printf( “%d\n”, a[0]);
scanf( “%d”, a );
printf( “%d \n”, a[0]);
}

17 [email protected]
DAVV
SCS

Arrays as Function Parameters


 The array address (i.e., the void inc_array(int a[ ],int size);
value of the array name), is main()
passed to the function {
inc_array( )
int test[3]={1,2,3};
 It is passed by value int ary[4]={1,2,3,4};
int i;
void inc_array(int a[ ], int size) inc_array(test,3);
{ for(i=0;i<3;i++)
int i; printf("%d\n",test[i]);
for(i=0;i<size;i++) inc_array(ary,4);
{ for(i=0;i<4;i++)
a[i]++; printf("%d\n",ary[i]);
} return 0;
}
}

18 [email protected]
DAVV
SCS

Example
Actual parameter
void bubbleSort(int a[ ],int size) corresponding to formal
{ parameter a[ ] can be
any array of int values;
int i, j, x; its declared size does not
for(i=0; i < size; i++) matter
for(j=i; j > 0; j--)
if(a[ j ] < a[ j-1])
{ /* Switch a[ j ] and a[ j-1] */
x=a[ j ]; a[ j ]=a[ j-1]; a[j-1]=x;
} Function bubbleSort( ) sorts
the first size elements of
}
array a into ascending order

19 [email protected]
Devi Ahilya Vishwavidyalaya

Pointers

The likelihood of a program crashing is in direct proportion to


the number of pointers used in it.

School of Computer Science [email protected]


DAVV
SCS

Pointer Variables
 Pointers are often referred to as references
 The value in a pointer variable is interpreted as a memory address
 Usually, pointer variables hold references to specific kinds of data (e.g.:
address of an int, address of a char, etc)

int * p; /* variable p can hold the address of a


memory location that contains an int */
char * chptr; /* chptr can hold the address of a
memory location that contains a char */

21 [email protected]
DAVV
SCS

Dereferencing Operator

 The expression *p denotes the memory cell to which p points


 Here, * is called the dereferencing operator
 Be careful not to dereference a pointer that has not yet been
initialized:

int *p; Address in p could


p ? be any memory
location

*p = 7; Attempt to put a value into an unknown


memory location will result in a run-time
error, or worse, a logic error

22 [email protected]
DAVV
SCS

The Address Operator


 The expression &x denotes the address of a variable x
 Here, & is called the address operator or the reference
operator

int x, *p;
x ? p ?

p = &x;
x ? p Value of x has
*p = 4; been changed
by *p = 4;
x 4 p

23 [email protected]
DAVV
SCS

The Null Pointer


 The null pointer is a special constant which is used to explicitly indicate
that a pointer does not point anywhere
 NULL is defined in the standard library <stdlib.h>
 In diagrams, indicated as one of:

NULL •

24 [email protected]
DAVV
SCS

Pointer Example
int *p, x, y, *q = NULL;
p = &x;
*p = 4;

p x 4 y ? q .
(or *p)
p = &y;

p x 4 y ? q .
*p is now another
name for y

25 [email protected]
DAVV
SCS

Pointer Example

*p = 8;

p x 4 y 8 . q

*p
q = p;

p x 4 y 8 q

*p or *q

26 [email protected]
DAVV
SCS

Pointer Example

p = &x;

p x 4 y 8 q

*p *q
*p = *q;

p x 8 y 8 q

*q
*p

27 [email protected]
DAVV
SCS

Arrays of Pointers
 It’s possible to have arrays of pointers
 The array name is a pointer to an array of pointers:

int * arrayOfPtr[ 4];


Pointers in array are not
int j = 6; k = 4;
initialized yet

6 j 4 k ? ? ? ?

arrayOfPtr 0 1 2 3

28 [email protected]
DAVV
SCS

Arrays of Pointers
arrayOfPtr[0] = &k;
arrayOfPtr[2]=&j;

6 4
? ?

j k arrayOfPtr 0 1 2 3

29 [email protected]
DAVV
SCS

Array Names as Pointers


 Array name is really a pointer to the first element in the array
 Consider the declaration int arr[5];
 arr has the same meaning as &arr[0]
 *arr has the same meaning as arr[0]
 Indexing into an array is really a pointer dereferencing operation

30 [email protected]
DAVV
SCS

Array Names as Pointers


 Array name is really a pointer to the first element in the array
 Consider the declaration int arr[5];
 a[0] is same as *a or *(a+0)
 Similarly a[2] is same as *(a+2)
 Now *(a+2) is same as *(2+a)
 So 2[a] is same as a[2]

Therefore a[2], *(a+2), *(2+a) and 2[a].

31 [email protected]
DAVV
SCS

Generic Pointers
 Sometimes we need to use pointer variables that aren’t associated with
a specific data type
 In C, these generic pointers simply hold memory addresses, and are
referred to as pointers to void:

void* ptr;

32 [email protected]
DAVV
SCS

Generic Pointers
 Any kind of pointer can be stored in a variable whose type is void*
 If we know that a value in a pointer p of type void* is really of a specific
pointer type x, and we want to treat the value p points to as a value of
type x, we have to cast the pointer to type x

33 [email protected]
DAVV
SCS

Generic Pointer Example


void * arr[6];
int j=7;
double k = 5.9;
int * n;
x ? k 5.9
double x;

n ? j 7

arr ? ? ? ? ? ?

0 1 2 3 4 5

34 [email protected]
DAVV
SCS

Generic Pointer Example

arr[2] = (void*)&j; // type cast is okay, but not needed here

x ? k 5.9

n ? j 7

? ? ? ? ?
arr
0 1 2 3 4 5

35 [email protected]
DAVV
SCS

Generic Pointer Example

arr[5] = &k; // cast not needed, but could be used

x ? k 5.9

n ? j 7

? ? ? ? ?
arr
0 1 2 3 4 5

36 [email protected]
DAVV
SCS

Generic Pointer Example

n = (int*)arr[2]; // cast is required here

x ? k 5.9

n 7
j

? ? ? ?
arr
0 1 2 3 4 5

37 [email protected]
DAVV
SCS

Generic Pointer Example

x = *((double*)arr[5]); // cast is required here

x 5.9 k 5.9

n 7
j

? ? ? ?
arr
0 1 2 3 4 5

38 [email protected]
Devi Ahilya Vishwavidyalaya

Dynamic Memory Allocation

Address allotment on the fly

School of Computer Science [email protected]


DAVV
SCS

Dynamic Memory Allocation


 Up to now, any variables, including pointers, that we’ve created have
been static:
 They exist only while the module in which they’ve been created is
still executing
 They disappear automatically upon exit from the module

40 [email protected]
DAVV
SCS

Dynamic Memory Allocation


 We can create entities such as ints, chars, arrays and complex data
structures that will persist beyond exit from the module that built them
 This method of creating objects is called dynamic allocation of
memory

41 [email protected]
DAVV
SCS

Dynamic Memory Allocation


 Statically allocated variables are created within a call frame on the
call stack
 Dynamically allocated variables are created an area of memory
known as the heap

42 [email protected]
DAVV
SCS

Dynamic Memory Allocation in C


 Requires the use of pointer variables, and of one of the memory
allocation functions from <stdlib.h>
 malloc: the most commonly used memory allocation function
void * malloc( size_t size );
 Locates size consecutive bytes of free memory (memory that
is not currently in use) in the heap, and returns a generic
pointer to the block of memory
 Returns NULL instead if size bytes can’t be found

43 [email protected]
DAVV
SCS

Dynamic Memory Allocation in C


 Value returned by malloc is a generic pointer, and must be cast to the
specific type of pointer the user intended to create

double * ptr;
ptr = (double *) (malloc( sizeof( double ) ) );

44 [email protected]
DAVV
SCS

Dynamic Memory Allocation in C


 Deallocation of dynamically allocated memory is not automatic
 No Java-style garbage collection occurs
 Programmer is responsible for recycling any dynamically allocated
memory that is no longer needed
 Must use the free( ) function from <stdlib.h>

45 [email protected]
DAVV
SCS

Dynamic Memory Allocation in C


void free(void * ptr);
 Parameter ptr is a pointer to the first byte of an entity that was
allocated from the heap
 At run-time, C checks the actual type of the pointer parameter to
determine exactly how many bytes to deallocate
 Any attempt to access deallocated memory is unsafe

46 [email protected]
DAVV
SCS

Dynamic Allocation – Example 1

int *p; Call stack Heap

p ?

p = (int*)malloc(sizeof(int));

p ?
*p
*p = 24;

p 24 *p

free(p);
24 unstable
p memory

47 [email protected]
DAVV
SCS

Dynamic Allocation – Example 2


Pointer to an array:

double * arr; Call stack Heap

arr ?

arr = (double*)(malloc(5*sizeof(double)));

arr ? ? ? ? ?

arr[2] = 8.0;
arr ? ? 8.0 ? ?

48 [email protected]
DAVV
SCS

Dynamic Allocation – Example 3


The following program is
wrong
This one is correct:
#include <stdio.h>
#include <stdio.h> int main()
int main() {
int *p;
{
p = (int*)
int *p;
(malloc(sizeof(int)));
scanf("%d",p);
scanf("%d",p);
… …
return 0; return 0;
} }

49 [email protected]
DAVV
SCS

Dynamic Allocation – Example 4

Allocating an array of pointers:

int ** ptrArray;
int k = 7;
ptrArray = (int**)(malloc( 4*sizeof(int*)));

Call stack Heap

ptrArray ? ? ? ?

k 7

50 [email protected]
DAVV
SCS

Dynamic Allocation – Example 4


ptrArray[0] = &k;
ptrArray[3] = (int*)(malloc(sizeof(int));

Call stack Heap

ptrArray ? ?

k 7
? *(ptrArray[3])

51 [email protected]
DAVV
SCS

Dynamic Memory Allocation in C


 calloc: Another commonly used memory allocation function
void *calloc(size_t nitems, size_t size);
 Locates (nitems*size) consecutive bytes of free memory
(memory that is not currently in use) in the heap, and returns
a generic pointer to the block of memory
 Returns NULL instead if size bytes can’t be found

52 [email protected]
Devi Ahilya Vishwavidyalaya

Pointers as Parameters in C

School of Computer Science [email protected]


DAVV
SCS

#include <stdio.h>
Example:
void add1(int a, int *b) { add1 accepts as parameters an int
a++; (*b)++; a and a pointer to int b
printf(“%d\n”, a); The call in the main is made, a is
printf(“%d\n”, *b); associated with a copy of main
return program variable j, and b is
associated with a copy of the
}
address of main program variable k
int main() {
int j = 4; k = 8;
Output from the program is:
add1( j, &k ); 5 (in add1)
printf(“%d\n”, j); 9
printf(“%d\n”, k);
4 (back in main)
return 0;
}
9

54 [email protected]
DAVV
SCS

#include <stdio.h> Example (cont’d):


void add1(int a, int *b) {
Call stack immediately before
a++; (*b)++;
the call to add1:
printf(“%d\n”, a);
printf(“%d\n”, *b);
return
}
int main() {
int j = 4; k = 8;
add1( j, &k );
printf(“%d\n”, j);
printf(“%d\n”, k);
j 4 k 8
return 0;
}

55 [email protected]
DAVV
SCS

#include <stdio.h> Example (cont’d):


void add1(int a, int *b) {
Call stack after the call to
a++; (*b)++;
add1, but before a++; is
printf(“%d\n”, a);
executed:
printf(“%d\n”, *b);
return
}
int main() {
int j = 4; k = 8; 4
a b
add1( j, &k );
printf(“%d\n”, j);
printf(“%d\n”, k);
j 4 k 8
return 0;
}

56 [email protected]
DAVV
SCS

#include <stdio.h>
Example (cont’d):
void add1(int a, int *b) { After a++; is executed
a++; (*b)++;
printf(“%d\n”, a);
printf(“%d\n”, *b);
return
}
int main() {
int j = 4; k = 8; 5
a b
add1( j, &k );
printf(“%d\n”, j);
printf(“%d\n”, k);
j 4 k 8
return 0;
}

57 [email protected]
DAVV
SCS

#include <stdio.h>
Example (cont’d):
void add1(int a, int *b) { After (*b)++; is executed
a++; (*b)++;
printf(“%d\n”, a);
printf(“%d\n”, *b);
return
}
int main() {
int j = 4; k = 8; 5
a b
add1( j, &k );
printf(“%d\n”, j);
printf(“%d\n”, k);
j 4 k 9
return 0;
}

58 [email protected]
DAVV
SCS

#include <stdio.h> Example (cont’d):


void add1(int a, int *b) {
Upon returning from add1, its
a++; (*b)++;
call frame is popped from the
printf(“%d\n”, a);
call stack, and execution
printf(“%d\n”, *b);
continues at the first printf in
return
main
}
int main() {
int j = 4; k = 8;
add1( j, &k );
printf(“%d\n”, j);
printf(“%d\n”, k);
return 0; j 4 k 9
}

59 [email protected]
DAVV
SCS

Example: Pointer Parameters


 Suppose that a function has the prototype:

void fn( double * x, int ** k)

• Inside fn, x is of type double*, and *x is of type


double
• k is of type int**, *k is of type int*, and **k is of type
int

60 [email protected]
DAVV
SCS

Example: Pointer Parameters (cont’d)


 Assume the main program declarations:

double p=6.3, q, *dptr1=&p, *dptr2;


int a, b=15, *c=&b, *d=&a, *e, **f, **g=&e;

p 6.3 dptr1
We will examine
? ?
a variety of valid
q dptr2
calls to fn

a ? d e ?
g
15 ?
b c f

61 [email protected]
DAVV
SCS

Example: Pointer Parameters (cont’d)


Function call:

fn ( &p, &c );
x k
Recall the
prototype:
p 6.3 dptr1 void fn( double * x,
int ** k)
q ? ? dptr2
Recall from main:

? ? int b,*c=&b;
a d e g
double p=6.3;
15 ?
b c f

62 [email protected]
DAVV
SCS

Example: Pointer Parameters (cont’d)


Function call:

fn ( dptr1, &d );
x k
Recall the
prototype:

p 6.3 dptr1 void fn( double * x,


int ** k)
q ? ? dptr2
Recall from main:
int a,*d=&a;
a ? d e ? g
double p=6.3,
15 ? *dptr1=&p;
b c f

63 [email protected]
DAVV
SCS

Example: Pointer Parameters (cont’d)


Function call:

fn ( &q, f );
x ?? k Danger: f doesn’t
point at anything yet

6.3 Recall the


p dptr1
prototype:
void fn( double * x,
q ? ? dptr2
int ** k)

a ? d e ? g Recall from main:


int ** f;
15 ??
b c f double q;

64 [email protected]
DAVV
SCS

Example: Pointer Parameters (cont’d)


Function call:

fn ( dptr2, &e);
?? x k Danger: dptr2 is
uninitialized

6.3 Recall the


p dptr1
prototype:
void fn( double * x,
q ? ?? dptr2
int ** k)

a ? d e ? g Recall from main:


int * e;
15 ?
b c f double * dptr2;

65 [email protected]
DAVV
SCS

Example: Pointer Parameters (cont’d)


Function call:

fn ( &p, g );
x k
Recall the
prototype:
p 6.3 dptr1 void fn( double * x,
int ** k)
q ? ? dptr2
Recall from main:
int *e, **g=&e;
a ? d e ? g
double p=6.3;
15 ?
b c f

66 [email protected]
DAVV
SCS

Why Use Pointer Parameters?


 So that the value being referenced can be modified by the function
 Efficiency: It takes less time and memory to make a copy of a reference
(typically a 2 or 4 byte address) than a copy of a complicated structure

67 [email protected]
DAVV
SCS

Arrays as Parameters
 C does not allow arrays to be copied as parameters
 Recall:
 Array name is really a pointer to the first element (location 0)
 Indexing with square brackets has the effect of dereferencing to a
particular array location

68 [email protected]
DAVV
SCS

Arrays as Parameters
 When we put an array name in a list of actual parameters, we are really
passing the pointer to the first element
 Do not use the address operator & when passing an array

69 [email protected]
DAVV
SCS

Arrays as Parameters
 Suppose that we wish to pass an array of integers to a function fn, along
with the actual number of array locations currently in use
 The following function prototypes are equivalent:

void fn( int * arr, int size );


void fn( int [ ] arr, int size);

70 [email protected]
DAVV
SCS

#include <stdlib.h>
Example
void init1 ( int [ ] a, int s1, int * b, int s2 ) {
for (int j = 0; j < s1; j++)
Could use int *a
a[ j ] = j;
and int[ ] b instead
for (int k = 0; k < s2; k++)
b[ k ] = s2 - k;
}
We trace through
int main( ) {
this code on the
int s[4], *t; next few slides
t = (int*)(malloc(6*sizeof(int));
t[0] = 6;
init1( s, 4, t, t[0] );

71 [email protected]
DAVV
SCS

Example (cont’d)

Before the call to init1: After execution of:


int s[4], *t;
t = (int*)(malloc(6*sizeof(int));
s ? ? ? ?
t[0] = 6;

t 6 ? ? ? ? ?

Call stack – main variables Heap

72 [email protected]
DAVV
SCS

Example (cont’d)
After call to init1, but before its execution begins:
local vars j and k have been ignored in the call frame for init1

Function prototype:
a s1 b s2
void init1 ( int [ ] a, int s1,
4 6
int * b, int s2 );
Function call:

? ? ? ? init1( s, 4, t, t[0] );
s

t 6 ? ? ? ? ?
Call stack
Heap

73 [email protected]
DAVV
SCS

Example (cont’d)
After execution of init1, but before return to main:
local vars j and k have been ignored in the call frame for init1

After:
a s1 b s2
for (int j = 0; j < s1; j++)
4 6
a[ j ] = j;
for (int k = 0; k < s2; k++)

0 1 2 3 b[ k ] = s2 - k;
s

t 6 5 4 3 2 1
Call stack
Heap
74 [email protected]
DAVV
SCS

Example (cont’d)
After returning to main:

s 0 1 2 3

t 6 5 4 3 2 1

Heap
Call stack

Call frame for the call to init1 has been recycled

75 [email protected]
DAVV
SCS

Why Is ‘**’ Needed?


 We may want a function to initialize or change a pointer
 Notation can also be used when creating or passing an array of pointers

76 [email protected]
DAVV
SCS

#include <stdlib.h>
Example
#include<time.h>
void init2( int *** t, int ** j ) { Dynamic allocation in init2
int k = 3 + rand( )%10; creates an array of
*t = (int**)(malloc(k*sizeof(int*))); pointers for main program
*j = (int*)(malloc(sizeof(int))); variable v to point at, and
**j = k; an int location for q to point
} at; the value that q points
int main( ) { at is also initialized
int **v; int *q;
srand((unsigned int) time(NULL));
init2( &v, &q );
Trace follows on next
v[1] = q;
slides

77 [email protected]
DAVV
SCS

Example (cont’d)

Before the call to init2:

After declarations:

v ? int **v;
int *q;

q ?

Call stack

78 [email protected]
DAVV
SCS

Example (cont’d)

int** int*** int After the call to init2, but


j t k ? before body is executed:
Function prototype:
void init2( int *** t, int ** j );
Function call:
v ?
init2( &v, &q );
int**

q ?

int*

Call stack

79 [email protected]
DAVV
SCS

Example (cont’d)

int** int*** int After execution of:


j t k 7 int k = 3 + rand( )%10;
// pretend that k is now 7
*t = (int**)(malloc(k*sizeof(int*)));

v
? ? ? ? ? ? ?
int**

q ?
Heap
int*

Call stack

80 [email protected]
DAVV
SCS

Example (cont’d)

int** int*** int After execution of:


j t k 7 *j = (int*)(malloc(sizeof(int)));

v
? ? ? ? ? ? ?
int**

int* ?

Call stack Heap

81 [email protected]
DAVV
SCS

Example (cont’d)
int** int*** int After execution of:
j t k 7 **j = k;

v
? ? ? ? ? ? ?
int**

int* 7

Call stack Heap

82 [email protected]
DAVV
SCS

Example (cont’d)

After returning to the main program, the call stack


information for init2 has been recycled

v
? ? ? ? ? ? ?
int**

int* 7

Call stack Heap

83 [email protected]
DAVV
SCS

Example (cont’d)

And finally, after the execution of


v[1] = q;

v
? ? ? ? ? ?
int**

int* 7

Call stack Heap

84 [email protected]
DAVV
SCS

Using const with Parameters


 Use const with parameters that aren’t pointers to indicate that the formal
parameter will not be altered inside the function
 const is used with a pointer parameter to indicate that the entity being
referenced will not be changed

85 [email protected]
DAVV
SCS

Using const with Parameters

void tryConst ( const int k, const int *p ) {


k++; /* compile time error generated */
(*p) = 83; /* compile time error generated – attempt to
change value from the calling module
that p points at */
p = (int*)(malloc(sizeof(int)));
}

No warning from the final line: the value from the calling
module that’s being referenced is not modified; however,
the function’s copy of the value’s address changes

86 [email protected]
Devi Ahilya Vishwavidyalaya

Pointers as Function Return Values

School of Computer Science [email protected]


DAVV
SCS

Pointers as Return Values


 Functions can return pointers
 We can sometimes use this fact to reduce the complexity surrounding
dereferencing operations

88 [email protected]
DAVV
SCS

#include <stdlib.h>
Example
int * init3( int j ) {
int *k, t;
The function init3
k = (int*)malloc(j*sizeof(int)); dynamically allocates an
for (t=0; t<j; t++) array of int, initializes it,
k[t] = t; and returns a reference to
it; in this case, the array
return k;
has the capacity to hold 40
} integers
int main() {
int *q;
q = init3( 40 );

89 [email protected]
DAVV
SCS

Example (cont’d)
After the call to init3, but Function prototype:
before body is executed:
int * init3( int j );
int int int* Function call:

40 ? ? q = init3( 40 );
j t k

q ?

int*
Call stack

90 [email protected]
DAVV
SCS

Example (cont’d)

After execution of:


k = (int*)malloc(j*sizeof(int));
int int int*
for (t=0; t<j; t++)
j 40 t ? k k[t] = t;

q ? 0 1 2 3 … 39

int*
Call stack Value to be returned is in k
Heap

91 [email protected]
DAVV
SCS

Example (cont’d)

After returning from init3, and after execution of the


assignment statement:
q = init3( 40 );

q 0 1 2 3 … 39

int*
Call stack Heap

Portion of the call stack for the call to init3 has been recycled

92 [email protected]
DAVV
SCS

What Not to Do with Pointers


 Never let a function return a reference to a local variable within the function
 Never set a pointer parameter to the address of a local variable
 Reason: The temporary space in which local variables are stored is recycled
(reused) after the returning from the function, and the value being referenced
may be overwritten at the next function call

93 [email protected]
DAVV
SCS

#include <stdlib.h>
Example
#include <time.h>
int ** init4( int ** size ) {
Local variables k and arr
int k, *arr;
exist only while init4 is
k = (int) 5 + rand( )%10;
being executed
arr = (int*)malloc(k*sizeof(int));
*size = &k; // Wrong Values stored at those
return &arr; // Wrong locations will likely be
} overwritten the next time
int main() { any function is called
int ** vals, *numvals;
Values of vals and
srand((unsigned int) time(NULL));
vals = init4( &numvals );
numvals (in main) would

therefore be destroyed

94 [email protected]
DAVV
SCS

Example (cont’d)

After the call to init4, but


before body is executed:

Function prototype:
int* int** int
int ** init4( int ** size );
arr ? size k ?
Function call:
vals = init4( &numvals );

vals ? numvals ?

int** int*

Call stack

95 [email protected]
DAVV
SCS

Example (cont’d) After execution of:


k = 5 + rand( )%10;
// pretend k is now 8
arr = (int*)malloc(k*sizeof(int));
int** int int* *size = &k; // Wrong

size k 8 arr

Value to be returned is
address of arr

numvals vals ?
? ? ? ? ? ? ? ?
int* int**
Call stack Heap

96 [email protected]
DAVV
SCS

Example (cont’d) Here’s what would


happen after return, on
completion of the
assignment statement:
vals = init4( &numvals );
int** int int*

size k 8 arr Value to be returned is


address of arr

numvals vals
? ? ? ? ? ? ? ?
int* int**
Call stack Heap

97 [email protected]
DAVV
SCS

Example (cont’d) But, the portion of the


call stack for init4 is
recycled at this stage,
so vals and numvals
point at values that are
unstable (i.e.: likely to
8 change at any moment);
we’d lose the value 8
and the array’s address

numvals vals
? ? ? ? ? ? ? ?
int* int**
Call stack Heap

98 [email protected]
Devi Ahilya Vishwavidyalaya

Pointer Arithmetic

School of Computer Science [email protected]


DAVV
SCS

Pointer Arithmetic
 Pointers are really numeric memory addresses
 C allows programmers to perform arithmetic on pointers
 Most commonly used with arrays and strings, instead of indexing, but
can be used with any pointer
 We won’t use pointer arithmetic much, but you may need to understand
it to read text books and other people’s code

100 [email protected]
DAVV
SCS

Pointer Arithmetic
 When used with an int array a:
 a is a pointer to int, and points to a[0]
 a+1 points to array element a[1]
 a+2 points to array element a[2] , etc
 *(a+4) = 10; is equivalent to a[4] = 10;
 Can compare pointers using ==, !=, >, <=, etc

101 [email protected]
DAVV
SCS

Pointer Arithmetic
 More examples:
int a[10], *p, *q;
p = &a[2];
q = p + 3; /* q points to a[5] now */
p = q – 1; /* p points to a[4] now */
p++; /* p points to a[5] now */
p--; /* p points to a[4] now */
*p = 123; /* a[4] = 123 */
*q = *p; /* a[5] = a[4] */
q = p; /* q points to a[4] now */

102 [email protected]
DAVV
SCS

Pointer Arithmetic
 The difference between two pointers of the same type yields an int result

int a[10], *p, *q , i;


p = &a[2];
q = &a[5];
i = q - p; /* i is 3 */
i = p - q; /* i is –3 */
a[2] = 8; a[5] = 2;
i = *p - *q; /* i = a[2] – a[5] */

103 [email protected]
DAVV
SCS

Pointer Arithmetic
 Note that pointer arithmetic and int arithmetic are not, in general, the
same
 In our previous examples: on most computers, an int requires 4 bytes
(In Turbo C it is 2 Bytes) of storage
 Adding 1 to a pointer to int actually increments the address by 4, so
that it points at the next memory location beyond the current int
 Casting a pointer to the wrong type leads to pointer arithmetic errors

104 [email protected]
DAVV
SCS

Pointer Arithmetic
int a[10], *p, *q , i;
char s[25], *u, *v, k;
p = &a[2]; q = &a[5];
i = q - p; /* i is 3, but the difference between the two
addresses is 12: space for 3 ints */
q++; /* address in q actually goes up by 4 bytes */
u = &s[6]; v = &s[12];
i = v – u; /* i is 6, and the difference between the two
addresses is 6, because a char requires
only 1 byte of storage */
u++; /* u = &s[7]; address in u goes up 1 byte */

105 [email protected]
DAVV
SCS

Example

Write a function myStrLen that is equivalent to strlen


from <string.h>
size_t myStrLen( const char * s ) {
size_t count = 0;
while ( *s != ‘\0’ ) { We can change
the pointer s, but
count++;
not the string it
s++; points at
}
return count;
}

106 [email protected]
DAVV
SCS

Strings in C
 No explicit string type in C; strings are simply arrays of characters that
are subject to a few special conventions
 Example: char s [10]; declares a 10-element array that can hold a
character string of up to 9 characters
 Convention: Use the null character '\0' to terminate all strings

107 [email protected]
DAVV
SCS

Strings in C
 C does not know where an array ends at run time – no boundary
checking
 All C library functions that use strings depend on the null character being
stored so that the end of the string can be detected
 Example: char str [10] = {'u', 'n', 'i', 'x', '\0'};
 Length of str is 4 (not 5, and not the declared size of the array)

108 [email protected]
DAVV
SCS

Accessing Individual Characters


 Use indexing, just as for any other kind of array:
char s[10];
s[0] = 'h';
s[1] = 'i’;
s[2] = '!';
s[3] = '\0';
 Use single quotes with char literals, and double quotes with string literals

109 [email protected]
DAVV
SCS

String Literals
 Example: printf("Long long ago.");
 Other ways to initialize a string:

char s[10]="unix"; /* s[4] is automatically set to '\0’;


s can hold up to ten chars,
including ‘\0’ */
char s[ ]="unix"; /* s has five elements: enough to
hold the 4-character string plus
the null character */

110 [email protected]
DAVV
SCS

Printing Strings with printf ( )


char str[ ] = "A message to display";
printf ("%s\n", str);
 printf expects to receive a string parameter when it sees %s in the format
string
 Can be from a character array
 Can be another literal string
 Can be from a character pointer (more on this later)

111 [email protected]
DAVV
SCS

Printing Strings with printf ( )


 When printf encounters the format specifier %s, it prints characters from
the corresponding string, up until the null character is reached
 The null character itself is not printed
 If no null character is encountered, printing will continue beyond the
array boundary until either one is found, or a memory access violation
occurs

112 [email protected]
DAVV
SCS

Example
char str[11]="unix and c";

printf("%s\n", str);
str[6]='\0'; What output does this
printf("%s\n", str); code segment produce?
printf(str); printf("\n");
str[2]='%';
str[3]= ‘s';
printf(str,str);
printf("\n");

113 [email protected]
DAVV
SCS

Printing with puts( )

 The puts function is much simpler than printf for


printing strings
 Prototype of puts is defined in stdio.h:
int puts(const char * str); Use of const in
 More efficient than printf: the program doesn't need to this context
analyze the format string at run-time indicates that the
function will not
modify the string
parameter

114 [email protected]
DAVV
SCS

Printing with puts( )

 Example:
char sentence[ ] = "The quick brown fox\n";
puts(sentence);
 Prints out two lines:
The quick brown fox
this blank line is part of the output
 puts adds a newline ‘\n’ character following the string

115 [email protected]
DAVV
SCS

Inputting Strings with gets( )

 gets( ) gets a line from standard input


 The prototype is defined in stdio.h:
char *gets(char *str);
 str is a pointer to the space where gets will store the line, or a
character array
 Returns NULL (the null pointer) upon failure. Otherwise, it returns
str
 Note the additional meaning for operator *

116 [email protected]
DAVV
SCS

Inputting Strings with gets( )


 Example:
char your_line[100];
printf("Enter a line:\n");
gets(your_line);
puts("Your input follows:\n");
puts(your_line);
 Newline character is not stored, but the null character is
 Make sure the array is big enough to hold the line being
read; otherwise, input will overflow into other areas of
memory

117 [email protected]
DAVV
SCS

Inputting Strings with scanf( )


 To read a string include:
 %s scans up to but not including the next white space character
 %ns scans the next n characters or up to the next white space
character, whichever comes first
 Example:
/* Assume s1, s2 and s3 are char arrays */
scanf ("%s%s%s", s1, s2, s3);
scanf ("%5s%5s%5s", s1, s2, s3);

118 [email protected]
DAVV
SCS

Inputting Strings with scanf( )


 Note: No address operator (&) is used with the actual parameter when
inputting strings into character arrays: the array name is an address
already
 Difference between gets( ) and scanf( ):
 gets( ) read an entire line
 scanf("%s",…) reads only up to the next whitespace character

119 [email protected]
DAVV
SCS

Example
#include <stdio.h>
int main ( )
{
char lname[81], fname[81];
int count, age;
puts ("Enter the last name, first name, and age, separated");
puts ("by spaces; then press Enter \n");
count = scanf ("%s%s%d", lname, fname, &age);
printf ("%d items entered: %s %s %d\n",
count, fname, lname, age);
return 0;
}

120 [email protected]
DAVV
SCS

The C String Library


 String functions are provided in an ANSI standard string library
 Access this through its header file:
#include <string.h>
 Includes functions to perform tasks such as:
 Computing length of string
 Copying strings
 Concatenating strings
 Searching for a sub string or characters
 This library is guaranteed to be there in any ANSI standard implementation of C

121 [email protected]
DAVV
SCS

Functions from string.h


 strlen returns the length of a NULL terminated character string:
size_t strlen (const char * str) ;
 size_t: a type defined in string.h that is equivalent to an unsigned int
 char *str: points to a series of characters or is a character array ending with '\0'
 What’s wrong with:
char a[5]={‘a’, ’b’, ’c’, ’d’, ’e’}; strlen(a);

122 [email protected]
DAVV
SCS

Functions from string.h


 strcpy makes a copy of a string:
char *strcpy (char * destination, const char * source);
 A copy of the string at address source is made at destination
 String at source should be null-terminated
 destination should point to enough room
(at least enough to hold the string at source)
 The return value is the address of the copied string (that is, destination)

123 [email protected]
DAVV
SCS

Functions from string.h


 strcat concatenates strings:
char * strcat (char * str1, const char * str2);
Appends a copy of str2 to the end of str1
The result string is null-terminated
str2 is not modified
A pointer equal to str1 is returned
 Programmer must ensure that str1 has sufficient space to hold the
concatenated string

124 [email protected]
DAVV
SCS

Example
#include <string.h>
#include <stdio.h>
int main( )
{ Show the output
char str1[27] = "abc";
char str2[100];
printf("%d\n",strlen(str1));
strcpy(str2,str1);
puts(str2);
puts("\n");
strcat(str2,str1);
puts(str2);
}

125 [email protected]
DAVV
SCS

Functions from string.h


 strcmp compares strings for equality or inequality:
int strcmp (const char *str1, const char *str2);
 Returns an int whose value is interpreted as follows:
< 0 : str1 is less than str2
0 : str1 is equal to str2
> 0 : str1 is greater than str2

126 [email protected]
DAVV
SCS

Functions from string.h


 strcmp compares the strings one char at a time until a difference is
found; return value is (the ASCII ordinal value of the char from str1)
minus (the ASCII ordinal value of the char from str2)
 If both strings reach a '\0' at the same time, they are considered equal,
and return value is zero

127 [email protected]
DAVV
SCS

Functions from string.h


 Other string comparison functions:
int strncmp (const char *str1,
const char * str2, size_t n);
 Compares at most n chars of str1 and str2
 Continues until a difference is found in the first n chars, or n
chars have been compared without detecting a difference,
or the end of str1 or str2 is encountered

128 [email protected]
DAVV
SCS

Functions from string.h


 strcasecmp( ) and strncasecmp( ): same as strcmp( ) and
strncmp( ), except that differences between upper and
lower case letters are ignored

129 [email protected]
DAVV
SCS

Functions from string.h

Show the output


#include <string.h>
int main()
{
char str1[ ] = "The first string.";
char str2[ ] = "The second string.";
printf("%d\n", strncmp(str1, str2, 4) );
printf("%d\n", strncmp(str1, str2, 7) );
}

130 [email protected]
DAVV
SCS

Functions from string.h

 strchr: Find the first occurrence of a specified


character in a string:
char * strchr (const char * str, int ch) ;
Search the string referenced by str from its
beginning, until either an occurrence of ch is
found or the end of the string (‘\0’) is reached
Return a pointer to the first occurrence of ch
in the string; if no occurrence is found, return
the NULL pointer instead

131 [email protected]
DAVV
SCS

Functions from string.h

Value returned by strchr can be used to


determine the position (index) of the character in
the string:
Subtract the start address of the string from
the value returned by strchr
This is pointer arithmetic: the result is offset
of the character, in terms of char locations,
from the beginning of the string
Will work even if sizeof(char) is not 1

132 [email protected]
DAVV
SCS

Functions from string.h


#include<stdio.h>
#include<string.h>
int main( )
{
char ch='b', buf[80];
strcpy(buf, "The quick brown fox");
if (strchr(buf,ch) == NULL)
printf ("The character %c was not found.\n",ch);
else
printf ("The character %c was found at position %d\n",
ch, strchr(buf,ch)-buf+1);
}

‘b’ is the 11th character in buf; in fact, it is stored in buf[10]

133 [email protected]
DAVV
SCS

Functions from string.h

 strstr searches for the first occurrence of one string inside


another:
char * strstr (const char * str,
char * query) ;
 If found, a pointer to the first occurrence of query
inside str is returned; otherwise the NULL pointer is
returned

134 [email protected]
DAVV
SCS

Functions from stdio.h

 sprintf behaves like printf, except that, instead of sending a


formatted stream of characters to standard output, it stores the
characters in a string
int sprintf( char *s, const char *format, …);
 Result is stored in the string referenced by s
 Useful in formatting a string, and in converting int or float values to
strings
 sscanf works like scanf, but takes its input from a string

135 [email protected]
DAVV
SCS

Functions from string.h and stdio.h

#include <stdio.h>
#include <string.h>
int main( )
{
char result[100];
sprintf(result, "%f", (float)17/37 );
if (strstr(result, "45") != NULL)
printf("The digit sequence 45 is in 17 divided by 37. \n");
return 0;
}

136 [email protected]
DAVV
SCS

Functions from stdlib.h

 atoi: takes a character string and converts it to an integer


int atoi (const char *ptr);
 Ignores leading white space in the string
 Then expects either + or – or a digit
 No white space allowed between the sign and the first digit
 Converts digit by digit until a non-digit (or the end of the
string) is encountered

137 [email protected]
DAVV
SCS

Functions from stdlib.h

 Examples using atoi :


string s atoi( s )
“394” 394
“157 66” 157
“-1.6” -1
“ +50x” 50
“twelve” 0
“x506” 0
“ - 409” 0

138 [email protected]
DAVV
SCS

Functions from stdlib.h


long atol (const char *ptr) ;
 like atoi, but returns a long
double atof (const char * str);
 Like atoi, but for real values
 Handles a decimal point, and an exponent indicator (e or E)
followed by an integer exponent
 string s atof( s )
“12-6” 12.000000
“ -0.123.456” -0.123000
“123E+3” 123000.000000
“123.1e-5” 0.001231

139 [email protected]
Devi Ahilya Vishwavidyalaya

Variable Number of Arguments/Parameters

School of Computer Science [email protected]


DAVV
SCS

Variable-Length Argument Lists


 Functions with unspecified number of arguments
 Load <stdarg.h>
 Use ellipsis(...) at end of parameter list
 Need at least one defined parameter
 Example:
double myfunction ( int i, ... );
 The ellipsis is only used in the prototype of a function with a variable
length argument list
 printf is an example of a function that can take multiple arguments
 The prototype of printf is defined as
int printf( const char* format, ... );

141 [email protected]
DAVV
SCS

Variable-Length Argument Lists


 Macros and definitions of the variable arguments header (stdarg.h)
 va_list
Type specifier, required (va_list arguments;)
 va_start( arguments, other variables )
Intializes parameters, required before use
 va_arg( arguments, type )
Returns a parameter each time va_arg is called
Automatically points to next parameter
 va_end( arguments )
Helps function have a normal return

142 [email protected]
Devi Ahilya Vishwavidyalaya

Command Line Arguments/Parameters

School of Computer Science [email protected]


DAVV
SCS

Passing Parameters to C
 Often a user wants to pass parameters into the program from
the command prompt
:\tc\bin>progname arg1 arg2 arg3
 This is accomplished in C using argc and argv

Number of arguments, which Array of strings of length argc,


includes the name of the executable with one argument per location

int main (int argc, char *argv[ ] ) {


/* Statements go here */
}

144 [email protected]
DAVV
SCS

Passing Parameters to C
#include <stdio.h>
int main(int argc, char *argv[ ])
{
int count;
printf ("Program name: %s\n", argv [0]);
if (argc > 1)
{
for (count=1; count<argc; count++)
printf ("Argument %d: %s\n",count,argv[count]);
}
else
puts ("No command line arguments entered.");
return 0;
}

145 [email protected]
DAVV
SCS

Passing Parameters to C

 Suppose we compiled the previous program to the executable file


myargs

C:\tc\bin>myargs first "second arg" 3 4 > myargs.out

 myargs.out contains the following lines:


Program name: myargs
Argument 1: first
Argument 2: second arg
Argument 3: 3
Argument 4: 4

146 [email protected]
DAVV
SCS

Passing Parameters to C
 C program should check the command line arguments for validity:
 Are there the right number of arguments?
 Are numeric arguments in the expected range of acceptable values?
 If an argument is an input or output file, can it be opened
successfully?
 Issue an error message and abort execution if arguments are
incorrect

147 [email protected]
Devi Ahilya Vishwavidyalaya

Compiler Directives

School of Computer Science [email protected]


DAVV
SCS

The C Preprocessor
 The C preprocessor is invoked by the compilation command before compiling
begins
 Changes your source code based on instructions called preprocessor
directives that are embedded in the source code
 The preprocessor creates a new version of your program and it is this new
program that actually gets compiled

149 [email protected]
DAVV
SCS

The C Preprocessor
 Normally, you do not see these new versions on the hard disk, as they
are deleted after compilation
 You can force the compiler to keep them to see the results
 Each preprocessor directive appears in the source code preceded by a
‘#’ sign

150 [email protected]
DAVV
SCS

The #define Directive


 Simple substitution macros
#define text1 text2
 This tells the compiler to find all occurrences of “text1” in the source code and
substitute “text2”
 Usually used for constants:
#define MAX 1000
 Generally use upper case letters (by convention)
 Always separate using white space
 No trailing semi-colon

151 [email protected]
DAVV
SCS

The #define Directive

#include <stdio.h>
#define PI 3.1416
#define PRINT printf
int main( )
{
PRINT(“Approximate value of pi: %f”, PI);
return 0;
}

152 [email protected]
DAVV
SCS

Function Macros
 You can also define function macros:
#define MAX(A,B) ( (a) > (b) ? (a) : (b) )
……
printf("%d", 2 * MAX(3+3, 7)); /* is equivalent to */
printf("%d", 2 * ( (3+3) > (7) ? (3+3) : (7) );
 The parentheses are important:
#define MAX(A,B) a>b?a:b
printf("%d", 2 * MAX(3+3, 7)); /*is equivalent to */
printf("%d", 2 * 3+3 > 7 ? 3+3 : 7 );

153 [email protected]
DAVV
SCS

Function Macros Should be Used with Care

#define MAX(X,Y) ((x)>(y)?(x):(y))


……
int n, i=4, j=3;
n= MAX( i++, j); /* Same as n= (( i++ )>( j )?( i++ ):( j )) */
printf("%d,%d,%d", n, i, j);

 The output is: 5, 6, 3


 If MAX was a function, the output would have been: 4, 5, 3

154 [email protected]
DAVV
SCS

Conditional Compilation
 The pre-processor directives #if, #elif, #else, and #endif tell the compiler if the
enclosed source code should be compiled
 Structure:
#if condition_1
statement_block_1
#elif condition_2
statement_block_2
...
#elif condition_n
Any constant expression
statement_block_n • If true (non-zero), compile
#else statement_block_1
default_statement_block • If false (zero), don't compile
#endif statement_block_1

155 [email protected]
DAVV
SCS

Conditional Compilation
 For the most part, the only things that can be tested are the things that
have been defined by #define statements

#define ENGLAND 0
#define FRANCE 1
#define ITALY 0
#if ENGLAND
#include "england.h"
#elif FRANCE
#include "france.h"
#elif ITALY
#include "italy.h"
#else
#include "canada.h"
#endif

156 [email protected]
DAVV
SCS

Conditional Compilation
 Conditional compilation can also be very useful for including debugging code
 When you are debugging your code you may wish to print out some
information during the running of your program
 You may not need want this extra output when you release your program;
you’d need to go back through your code to delete the statements

157 [email protected]
DAVV
SCS

Conditional Compilation
 Instead, you can use #if … #endif to save time:
#define DEBUG 1
……
#if DEBUG
printf("Debug reporting at function my_sort()!\n");
#endif
……
 Change DEBUG to zero and recompile to suppress the debugging
output

158 [email protected]
DAVV
SCS

Conditional Compilation
 We can use a preprocessor function as the condition of
compilation:
defined ( NAME )
Returns true if NAME has been defined; else false
 Example:
#define DEBUG
#if defined ( DEBUG )
printf("debug report at function my_sort() \n");
#endif

159 [email protected]
DAVV
SCS

Conditional Compilation
 Note: Value of the defined function depends only on whether
the name DEBUG has been defined
 It has nothing to do with which value (if any) DEBUG is
defined to; in fact, we don’t have to provide a value at all
 Can use the notation #ifdef NAME instead
 We also have #ifndef (if not defined)

160 [email protected]
DAVV
SCS

Conditional Compilation
 The #undef … directive makes sure that defined( …) evaluates to false.
 Example: Suppose that, for the first part of a source file, you want
DEBUG to be defined, and for the last part, you want DEBUG to be
undefined

161 [email protected]
DAVV
SCS

Conditional Compilation
 A directive can also be set on the Unix/DOS command line at compile
time:
tcc/cc –DDEBUG myprog.c
Compiles myprog.c with the symbol DEBUG defined
as if #define DEBUG was in written at the top of
myprog.c

162 [email protected]
DAVV
SCS

The #include Directive


 Causes all of the code in the included file to be inserted at the point in
the text where #include appears
 Included files can contain other #include directives; usually limited to 10
levels of nesting
 < > tells the compiler to look in the standard include directories
 " " tells the compiler to first find it in current folder than in include
directory

163 [email protected]
DAVV
SCS

The #include Directive


 In large programs, some .h files may be #included several times – could lead to
multiple definition errors
 To avoid this problem, surround contents of the .h file with
#ifndef unique_identifier_name
# define unique_identifier_name
/* contents of .h file belong here */
#endif

164 [email protected]
Devi Ahilya Vishwavidyalaya

Structures and Union

School of Computer Science [email protected]


DAVV
SCS

Structures in C
 Structures are used in C to group together related data into a composite
variable. This technique has several advantages:
 It clarifies the code by showing that the data defined in the structure
are intimately related.
 It simplifies passing the data to functions. Instead of passing multiple
variables separately, they can be passed as a single unit.

166 [email protected]
DAVV
SCS

Structures
 Structure: C’s way of grouping a collection of data into a single
manageable unit
 Defining a structure type:
struct coord {
int x ;
int y ;
};
 This defines a new type struct coord; no variable is actually declared
or generated

167 [email protected]
DAVV
SCS

Defines the
Structures structured type struct
coord and statically
To define struct variables: allocates space for
struct coord { two structures, first
int x,y ; and second; the
structures are not
} first, second; initialized
Another approach:
struct coord {
int x,y ; Just defines the
}; structured type
............... Statically allocated
struct coord first, second; variables are
declared here
struct coord third;
168 [email protected]
DAVV
SCS

Structures
 You can use a typedef if you want to avoid two-word type names such as
struct coord:
typedef struct coord coordinate;
coordinate first, second;
 In some compilers, and all C++ compilers, you can usually simply say
just:
coord first, second;

169 [email protected]
DAVV
SCS

Structures
 Type definition can also be written as:
typedef struct coord {
int x,y ;
} coordinate;
 In general, it’s best to separate the type definition from
the declaration of variables

170 [email protected]
DAVV
SCS

Structures
 Access structure members by the dot (.) operator
 Generic form:
structure_var.member_name
 For example:
coordinate pair1, pair2;
pair1.x = 50 ;
pair2.y = 100;

171 [email protected]
DAVV
SCS

Structures
 struct_var.member_name can be used anywhere a variable can be
used:
 printf ("%d , %d", second.x , second.y );
 scanf("%d, %d", &first.x, &first.y);

172 [email protected]
DAVV
SCS

Structures
 Can copy entire structures using =
pair1 = pair2;
performs the same task as:
pair1.x = pair2.x ;
pair1.y = pair2.y ;

173 [email protected]
DAVV
SCS

Memory alignment/ Structure Padding


 Compiler inserts unused bytes into the structure to align the memory on a
word boundary.
 Different C compilers may give different offsets to the elements.

174 [email protected]
DAVV
SCS

Structures Containing Structures

 Structures can have other structures as members:


 To define rectangle in terms of coordinate:
typedef struct rect {
coordinate topleft;
coordinate bottomright;
} rectangle;

? ? ? ? Rectangle blueprint
x y x y

topleft bottomright

175 [email protected]
DAVV
SCS

Structures Containing Structures

 To initialize the points describing a rectangle:


struct rect mybox ;
mybox.topleft.x = 0 ;
mybox.topleft.y = 10 ;
mybox.bottomright.x = 100 ;
mybox.bottomright.y = 200 ;

0 10 100 200 struct rect


x y x y

topleft bottomright

176 [email protected]
DAVV
SCS

int main ( )
Example {
int length, width;
#include <stdio.h> long area;
typedef struct coord { rectangle mybox;
int x; mybox.topleft.x = 0;
int y; mybox.topleft.y = 0;
}coordinate; mybox.bottomright.x = 100;
typedef struct rect { mybox.bottomright.y = 50;
coordinate topleft; width = mybox.bottomright.x –
coordinate bottomright; mybox.topleft.x;
}rectangle; length = mybox.bottomright.y –
mybox.topleft.y;
area = width * length;
printf (“Area is %ld units.\n", area);
}

177 [email protected]
DAVV
SCS

Structures Containing Arrays


 Arrays within structures are the same as any other member
element
 Example:
struct record {
float x; record
char y [5] ;
};

float char[5]

178 [email protected]
DAVV
SCS

Example #include <stdio.h>


struct data
{
float amount;
char fname[30];
char lname[30];
} rec;
int main () {
struct data rec;
printf ("Enter the donor's first and last names, \n");
printf ("separated by a space: ");
scanf ("%s %s", rec.fname, rec.lname);
printf ("\nEnter the donation amount: ");
scanf ("%f", &rec.amount);
printf ("\nDonor %s %s gave $%.2f.\n",
rec.fname,rec.lname,rec.amount);
}

179 [email protected]
DAVV
SCS

Arrays of Structures

 Example:
struct entry {
char fname [10] ;
char lname [12] ;
char phone [8] ; This creates an
array of 1000
}; structures of type
struct entry list [1000]; struct entry
 Possible assignments:
list [1] = list [6];
strcpy (list[1].phone, list[6].phone);
list[6].phone[1] = list[3].phone[4] ;

180 [email protected]
DAVV
SCS

int main() {
Example struct entry list[4];
int i;
#include <stdio.h> for (i=0; i < 4; i++) {
struct entry { printf ("\nEnter first name: ");
char fname [20]; scanf ("%s", list[i].fname);
char lname [20]; printf ("Enter last name: ");
char phone [10]; scanf ("%s", list[i].lname);
}; printf ("Enter phone in 123-4567 format: ");
scanf ("%s", list[i].phone);
}
printf ("\n\n");
for (i=0; i < 4; i++) {
printf ("Name: %s %s", list[i].fname,
list[i].lname);
printf ("\t\tPhone: %s\n", list[i].phone);
}
}

181 [email protected]
DAVV
SCS

Initializing Structures
• Example:
struct sale {
char customer [20] ;
char item [20] ;
int amount ;
};
struct sale mysale = { "Acme Industries",
"Zorgle blaster",
1000 } ;

182 [email protected]
DAVV
SCS

Initializing Structures
 Example: Structures within structures:
struct customer {
char firm [20] ;
char contact [25] ;
};
struct sale {
struct customer buyer ;
char item [20] ;
int amount ;
} mysale =
{ { "Acme Industries", "George Adams"} ,
"Zorgle Blaster", 1000
};

183 [email protected]
DAVV
SCS

Initializing Structures

• Example: Arrays of structures


struct customer { struct saley1990 [100] = {
char firm [20] ; { { "Acme Industries",
"George Adams"} ,
char contact [25] ;
“Widget" , 1000
};
},
struct sale {
{ { "Wilson & Co.",
struct customer buyer ; "Ed Wilson"} ,
char item [20] ; "Thingamabob" , 290
int amount ; }
}; };

184 [email protected]
DAVV
SCS

Pointers to Structures

struct part {
float price ;
char name [10] ;
};
struct part *p , thing;
p = &thing;
/* The following two statements are equivalent */
thing.price = 50;
(*p).price = 50; /* ( ) around *p is needed */

185 [email protected]
DAVV
SCS

Pointers to Structures

thing.price thing.name [ ]

 p is set to point to the first byte of the struct variable

186 [email protected]
DAVV
SCS

Pointers to Structures

 When we have a pointer to a structure, we must


dereference the pointer before attempting to access
the structure’s members
 The membership (dot) operator has a higher
precedence than the dereferencing operator

struct part *p , thing;


p = &thing;
(*p).price = 50; Parentheses around *p are necessary

187 [email protected]
DAVV
SCS

Pointers to Structures

C provides an operator -> that combines the


dereferencing and membership operations
into one, performed in the proper order
Easier form to read (and to type) when
compared with the two separate operators
struct part *p , thing;
p = &thing;
p->price = 50; /*equivalent to (*p).price = 50; and
thing.price = 50; and (&thing)->price = 50;*/

188 [email protected]
DAVV
SCS

Pointers to Structures

struct part * p, *q;


p = (struct part *) malloc( sizeof(struct part) );
q = (struct part *) malloc( sizeof(struct part) );
p -> price = 199.99 ;
strcpy( p -> name, "hard disk" );
(*q) = (*p);
q = p;
free(p);
free(q); /* This statement causes a problem.
Why? */

189 [email protected]
DAVV
SCS

Pointers to Structures
 You can allocate a structure array as well:
struct part *ptr;
ptr = (struct part *) malloc(10*sizeof(struct part) );
for( i=0; i< 10; i++)
{
ptr[ i ].price = 10.0 * i;
sprintf( ptr[ i ].name, "part %d", i );
}
……
free(ptr);
}

190 [email protected]
DAVV
SCS

Pointers to Structures

 You can use pointer arithmetic to access the elements of


the array:
{
struct part *ptr, *p;
ptr = (struct part *) malloc(10 * sizeof(struct part) );
for( i=0, p=ptr; i< 10; i++, p++)
{
p -> price = 10.0 * i;
sprintf( p -> name, "part %d", i );
}
……
free(ptr);
}

191 [email protected]
DAVV
SCS

Pointer as Structure Member


struct node{
int data;
struct node *next;
} a,b,c;

? ? ? ? ? ?
a b c
struct node a,b,c;
a.next = &b;
b.next = &c;
c.next = NULL;

? ? ? NULL
a b c
192 [email protected]
DAVV
SCS

Pointer as Structure Member


a.data = 1;
a.next->data = 2;
/* or b.data = 2; or (*(a.next)).data = 2 */
a.next->next->data = 3;
/* or c.data = 3; or (*(a.next)).next->data = 3;
or (* (*(a.next)).next).data = 3; or (*(a.next->next)).data = 3; */
c.next = (struct node *) malloc(sizeof(struct node));

1 2 3
a b c

Only this node has ? ?


been dynamically
allocated

193 [email protected]
DAVV
SCS

Assignment Operator vs. memcpy

/* This copies one struct into /* Equivalently, you can use memcpy */
another */ #include <string.h>
#include<string.h> {
{ struct part a,b;
struct part a,b; b.price = 39.99;
b.price = 39.99; strcpy(b.name,"floppy“);
strcpy(b.name,"floppy“); memcpy(&a,&b,sizeof(part));
a = b; }
}

194 [email protected]
DAVV
SCS

Array Member vs. Pointer Member


struct book {
float price;
char name[50];
};
int main( ) price price
{ 19.99 ?
struct book a,b; name name
b.price = 19.99;
C handbook ??????????
strcpy(b.name,
"C handbook");
b a
/* continued… */

195 [email protected]
DAVV
SCS

Array Member vs. Pointer Member


/* …continued… */ price price
a = b; 19.99 19.99
name name
C handbook C handbook

b a

/* …continued… */ price price


strcpy(b.name, 19.99 19.99
"Unix handbook"); name name
/*… rest of program */ Unix handbook C handbook

b a

196 [email protected]
DAVV
SCS

Array Member vs. Pointer Member


struct book {
float price; b a
char *name;
price price
};
19.99 ?
int main()
{ name name
struct book a,b; ?
b.price = 19.99;
b.name = (char *)
malloc(50);
strcpy(b.name,
C handbook
“C handbook”);
/* continued… */

197 [email protected]
DAVV
SCS

Array Member vs. Pointer Member


/* … continued… */ b a
a = b;
price price
/* … continued… */
19.99 19.99
name name

Values of the struct’s


members were copied
here; the string lies
C handbook
outside the structure,
and was not copied

198 [email protected]
DAVV
SCS

Array Member vs. Pointer Member


b a
/* … continued… */
strcpy(b.name, price price
"Unix handbook"); 19.99 19.99
/* …rest of program */ name name

This isn’t likely what we Unix handbook


wanted to happen here

199 [email protected]
DAVV
SCS

strdup() from <string.h>


 General form:
char * strdup (const char * source);
 strdup( ) makes a dynamically allocated copy of a string at source, and
returns a pointer to it; returns NULL instead if a copy can’t be made
 Size of the new string is strlen(source)

200 [email protected]
DAVV
SCS

strdup() from <string.h>


/* from earlier example */
struct book {
float price;  Instead of the calls to
malloc() and strcpy(), we
char *name;
can use
};
b.name = strdup(“C handbook”);
int main()
{  Only difference: b.name will
have the capacity to store
struct book a,b;
only 10 chars plus the null
b.price = 19.99;
character, rather than the 50
b.name = (char *) malloc(50); chars it held in the original
strcpy(b.name, codeSize of the new string is
“C handbook”); strlen(source)

201 [email protected]
DAVV
SCS

Passing Structures to Functions


 Structures are passed by value to functions
 The formal parameter variable will be a copy of the actual parameter in
the call
 Copying can be inefficient if the structure is big
 It is usually more efficient to pass a pointer to the struct

202 [email protected]
DAVV
SCS

Structures as Return Values


 A function can have a struct as its return value
 It may in general be more efficient to have a function return a pointer to a
struct, but be careful:
 Don’t return a pointer to a local variable
 It’s fine to return a pointer to a dynamically allocated structure

203 [email protected]
DAVV
SCS

Passing Structures to Functions


#include<stdio.h>
struct pairInt {
int min, max;
};
struct pairInt min_max(int x,int y)
{
struct pairInt pair;
pair.min = (x > y) ? y : x;
pair.max = (x > y) ? x : y;
return pairInt;
}
int main(){
struct pairInt result;
result = min_max( 3, 5 );
printf("%d<=%d", result.min, result.max);
}

204 [email protected]
DAVV
SCS

Passing Structures to Functions

#include<stdio.h>
struct book {
float price;
char abstract[5000];
};
void print_abstract( struct book
*p_book)
{
puts( p_book->abstract );
};

205 [email protected]
DAVV
SCS

Unions
 union
 Memory that contains a variety of objects over time
 Only contains one data member at a time
 Members of a union share space
 Conserves storage
 Only the last data member defined can be accessed
 union declarations
 Same as struct
union Number {
int x;
float y;
};
union Number value;

206 [email protected]
DAVV
SCS

Unions
 Valid union operations
 Assignment to union of same type: =
 Taking address: &
 Accessing union members: .
 Accessing members using pointers: ->

207 [email protected]
DAVV
SCS

Big and Little Endian Representations


 Endianness refers to the order that the individual bytes (not bits) of a multibyte
data element is stored in memory.
 Big endian is the most straightforward method. It stores the most significant byte
first, then the next significant byte and so on.
 Little endian stores the bytes in the opposite order (least significant first).
 The x86 family of processors use little endian representation.

208 [email protected]
DAVV
SCS

How to Determine Endianness

unsigned short word = 0x1234; /* assumes sizeof ( short) == 2 */


unsigned char p = (unsigned char ) &word;
if ( p[0] == 0x12 )
printf (”Big Endian Machine\n”);
else
printf (” Little Endian Machine\n”);

209 [email protected]
DAVV
SCS

When to Care About Little and Big Endian


 For typical programming, the endianness of the CPU is not
significant.
 The most common time that it is important is when binary data is
transferred between different computer systems.
 Since ASCII data is single byte, endianness is not an issue for it.

210 [email protected]
Devi Ahilya Vishwavidyalaya

Bitwise operator and Bit fields

School of Computer Science [email protected]


DAVV
SCS

Bit Fields
 Bit fields allow one to specify members of a struct that only use a
specified number of bits. The size of bits does not have to be a multiple
of eight.
 A bit field member is defined like an unsigned int or int member with a
colon and bit size appended to it.

212 [email protected]
DAVV
SCS

An example of bitfield

The first bitfield is assigned to the least significant bits of its word

213 [email protected]
DAVV
SCS

Bitwise Operators
 All data represented internally as sequences of bits
 Each bit can be either 0 or 1
 Sequence of 8 bits forms a byte
Operator Name Description
& bitwise AND The bits in the result are set to 1 if the corresponding
bits in the two operands are both 1.
| bitwise OR The bits in the result are set to 1 if at least one of the
corresponding bits in the two operands is 1.
^ bitwise exclusive OR The bits in the result are set to 1 if exactly one of the
corresponding bits in the two operands is 1.
<< left shift Shifts the bits of the first operand left by the number
of bits specified by the second operand; fill from right
with 0 bits.
>> right shift Shifts the bits of the first operand right by the number
of bits specified by the second operand; the method
of filling from the left is machine dependent.
~ One’s complement All 0 bits are set to 1 and all 1 bits are set to 0.

214 [email protected]
Devi Ahilya Vishwavidyalaya

Files in C

School of Computer Science [email protected]


DAVV
SCS

FILE *
 C uses the FILE* data type to access files
 FILE is defined in <stdio.h>

#include <stdio.h>
int main( )
{
FILE * fp;
fp = fopen("tmp.txt", "w");
fprintf(fp,"This is a test\n");
fclose(fp);
return 0;
}

216 [email protected]
DAVV
SCS

Opening a File

 Must include <stdio.h>


 Prototype form:
FILE * fopen (const char * filename, const char * mode)
 FILE is a structure type declared in stdio.h.
 Keeps track of the file mode (read, write, etc), position in the file that we’re
accessing currently, and other details
 May vary from system to system

217 [email protected]
DAVV
SCS

Opening a File

 fopen returns a pointer to a FILE structure


 Must declare a pointer of type FILE to receive that value when it is returned
 Use the returned pointer in all subsequent references to that file
 If fopen fails, NULL is returned.
 The argument filename is the name of the file to be opened

218 [email protected]
DAVV
SCS

Opening a File
 Enclose the mode in double quotes or pass as a string variable
 Modes are:
 r: open the file for reading; fopen returns NULL if the file doesn’t
exist or can’t be opened
 w: create file for writing; destroy old if file exists
 a: open for writing; create if not there; start at the end-of-file
(append mode)
 r+: open for update (r/w); create if not there; start at the beginning
 w+: create for r/w; destroy old if there
 a+: open for r/w;create if not there; start at the end-of-file

219 [email protected]
DAVV
SCS

Four Ways to Read and Write Files


 Formatted file I/O

 Get and put a character

 Get and put a line

 Block read and write

220 [email protected]
DAVV
SCS

Formatted File I/O


 Formatted file input is done through fscanf:
 int fscanf (FILE * fp, const char * fmt, ...) ;
 Formatted file output is done through fprintf:
 int fprintf(FILE *fp, const char *fmt, …);
 fscanf and fprintf work just like scanf and printf, except that a file pointer
is required

221 [email protected]
DAVV
SCS

Formatted File I/O

{ …
FILE *fp1, *fp2;
int n;
fp1 = fopen("file1", "r");
fp2 = fopen("file2", "w");
fscanf(fp1, "%d", &n);
fprintf(fp2, "%d", n);
fclose(fp1);
fclose(fp2);
}

222 [email protected]
DAVV
SCS

Get and Put a Character


#include <stdio.h>
int fgetc(FILE * fp);
int fputc(int c, FILE * fp);
 These two functions read or write a single byte from or to a file
 fgetc returns the character that was read, converted to an integer
 fputc returns the value of parameter c if it succeeds; otherwise, returns
EOF

223 [email protected]
DAVV
SCS

Get and Put a Line

#include <stdio.h>
char *fgets(char *s, int n, FILE * fp);
int fputs(char *s, FILE * fp);
 fgets reads an entire line into s, up to n-1 chars in length; includes the
newline char in the string, unless line is longer than n-1
 fgets returns the pointer s on success, or NULL if an error or end-of-file
is reached
 fputs returns the number of chars written if successful; otherwise,
returns EOF

224 [email protected]
DAVV
SCS

Closing and Flushing Files


int fclose (FILE * fp) ;
 Call to fclose closes fp -- returns 0 if it works, or1 if it fails
 Can clear a buffer without closing it
int fflush (FILE * fp) ;
 Essentially this is a force to disk
 Very useful when debugging
 Without fclose or fflush, updates to a file may not be written to the file
on disk. (Operating systems like Unix usually use “write caching” disk
access.)

225 [email protected]
DAVV
SCS

Detecting End of an Input File


 When using fgetc:
while ( (c = fgetc (fp) ) != EOF ) { … }
 Reads characters until it encounters the EOF char
 The problem is that the byte of data read may actually be indistinguishable
from EOF
 When using fgets:
while ( fgets( buf, bufsize, fp ) != NULL ) { … }
 Reads strings into buf until end of file is reached

226 [email protected]
DAVV
SCS

Detecting End of an Input File

 When using fscanf:


 Tricky to detect end of file: value of fscanf call will be less than the
expected value, but this condition can occur for a number of other
reasons as well
 In all these situations, end of file is detected only when we attempt to
read past it
 Function to detect end of file:
int feof (FILE * fp) ;
 Note: the feof function realizes the end of file only after a read
attempt has failed (fread, fscanf, fgetc)

227 [email protected]
DAVV
SCS

Example
#include<stdio.h>
#define BUFSIZE 100 This program echoes
int main ( ) { the contents of file1 to
char buf[BUFSIZE]; standard output with
if ( (fp=fopen("file1", "r"))==NULL) { one flaw: the last line is
fprintf (stderr,"Error opening file."); echoed twice; it would
exit (1); be better to use:
}
while (!feof(fp)) { while (fgets(buf, BUFSIZE,
fgets (buf,BUFSIZE,fp);
fp) != NULL)
printf ("%s",buf);
} printf(“%s”,buf);
fclose (fp);
return 0;
}

228 [email protected]
Devi Ahilya Vishwavidyalaya

Advanced File Features

School of Computer Science [email protected]


DAVV
SCS

Block Reading and Writing

 fread and fwrite are binary file reading and writing functions
 Prototypes are found in stdio.h
 Advantages of using binary files:
 Reading and writing are quick, since I/O is not being converted
from/to ASCII characters
 Large amounts of data can be read/written with a single function
call (block reading and writing)
 Disadvantage of using binary files:
 Contents are not easily read by humans

230 [email protected]
DAVV
SCS

Block Reading and Writing

 Generic form:
int fwrite (void *buf, int size, int count, FILE *fp) ;
int fread (void *buf, int size, int count, FILE *fp) ;
 buf: is a pointer to the region in memory to be written/read; it can be a
pointer to anything (a simple variable, an array, a structure, etc)
 size: the size in bytes of each individual data item
 count: the number of data items to be written/read

231 [email protected]
DAVV
SCS

Block Reading and Writing


 Example: We can write all 100 elements from an array of integers to a
binary file with a single statement
 fwrite( buf, sizeof(int), 100, fp);
 Bit patterns for 100*sizeof(int) bytes at address buf are copied
directly to the output file, without any type conversion
 The fwrite (fread) returns the number of items actually written (read)

232 [email protected]
DAVV
SCS

Block Reading and Writing


 Testing for errors:
if ((frwrite(buf,size,count,fp)) != count)
fprintf(stderr, "Error writing to file.");
 Writing value of a double variable x to a file:
fwrite (&x, sizeof(double), 1, fp) ;
 This writes the double x to the file in raw binary format
(I.e.: its internal machine format)

233 [email protected]
DAVV
SCS

Block Reading and Writing


 Writing an array text[50] of 50 characters can be done by:
 fwrite (text, sizeof(char), 50, fp) ;
or
 fwrite (text, sizeof(text), 1, fp); /* text must be a local array
name */
 fread and fwrite are more efficient than fscanf and fprintf: no
type conversions required

234 [email protected]
DAVV
SCS

Sequential and Random Access

 A FILE structure contains a long that indicates the position (disk


address) of the next read or write
 When a read or write occurs, this position changes
 You can rewind and start reading from the beginning of the file
again:
void rewind (FILE * fp) ;
 A call to rewind resets the position indicator to the
beginning of the file

235 [email protected]
DAVV
SCS

Sequential and Random Access

 To determine where the position indicator is, use:


long ftell (FILE * fp) ;
Returns a long giving the current position in
bytes
The first byte of the file is byte zero
If an error occurs, ftell () returns -1

236 [email protected]
DAVV
SCS

Random Access
 If we’re aware of the structure of a file, we can move the file’s position indicator
anywhere we want within the file (random access):
int fseek (FILE * fp, long offset, int origin) ;
 offset is the number of bytes to move the position indicator
 origin says where to move from

237 [email protected]
DAVV
SCS

Random Access
 Three options/constants are defined for origin:
 SEEK_SET: move the indicator offset bytes from the beginning
 SEEK_CUR: move the indicator offset bytes from its current position
 SEEK_END: move the indicator offset bytes from the end

238 [email protected]
DAVV
SCS

Random Access
 Random access is most often used with binary input files, when speed of
execution matters: we want to avoid having to read in data sequentially
to get to a known location
 Writing to a location in a file other than the end does not insert content: it
overwrites

239 [email protected]
DAVV
SCS

Example: End of File



fseek(fp,0,SEEK_END); /* position indicator is 0 bytes from
the end-of-file marker */
printf("%d\n", feof(fp)) /* Value printed is zero */
fgetc(fp); /* fgetc returns -1 (EOF) */
printf("%d\n",feof(fp)); /* Nonzero value, now that an attempt
has been made to read at the end
of the file */

240 [email protected]
DAVV
SCS

File Management Functions

 Erasing a file:
int remove (const char * filename);
This is a character string naming the file
Returns 0 if deleted, and -1otherwise
If no pathname is provided, attempts to delete the file
from the current working directory
Can fail for several reasons: file not found, user does not
have write privileges, file is in use by another process,
etc

241 [email protected]
DAVV
SCS

File Management Functions


 Renaming a file:
int rename (const char * oldname,
const char * newname);
Returns 0 if successful, or -1 if an error occurs
error: file oldname does not exist
error: file newname already exists
error: try to rename to another disk

242 [email protected]
DAVV
SCS

Using Temporary Files


 Temporary files: exist only during the execution of the program
 To generate a filename, use:
char *tmpnam (char *s) ;
 Creates a valid filename that does not conflict with any other existing files
 You then open it and write to it
 The file will continue to exist after the program executes unless you delete it
using remove()

243 [email protected]
DAVV
SCS

Example

#include <stdio.h>
int main () {
char buffer[25];
tmpnam(buffer);
printf ("Temporary name is: %s", buffer);
return 0;
}

Output:
Temporary name is: c:\tc\bin\aaaceaywB

244 [email protected]
DAVV
SCS

Implicitly Opened Files: stdin, stdout, and stderr

 Every C program has three files opened for them at start-up: stdin,
stdout, and stderr
 stdin (standard input) is opened for reading, while stdout (standard
output) and stderr (standard error) are opened for writing
 They can be used wherever a FILE * can be used
 Writing to stderr is a good practice when reporting error messages: it
causes all output buffers to be flushed (written), and aids debugging

245 [email protected]
DAVV
SCS

stdin, stdout, and stderr


 Examples:
 fprintf(stdout, "Hello there\n");
 This is the same as printf("Hello there\n");
 fscanf(stdin, "%d", &int_var);
This is the same as scanf("%d", &int_var);
 fprintf(stderr, "An error has occurred\n");
Will force anything in the stdout buffer or in the buffer for an
output file to be printed as well

246 [email protected]
DAVV
SCS

The exit () Function


 Used to abort the program at anytime from anywhere before the normal exit
location
 Syntax:
exit (status);
 Example:
#include <stdlib.h>
……
if( (fp=fopen("a.txt","r")) == NULL){
fprintf(stderr, "Cannot open file a.txt!\n");
exit(1);
}

247 [email protected]
Devi Ahilya Vishwavidyalaya

I/O Redirection, Unconditional Branching, Enumerated


Data Type, Little Endian and Big Endian

School of Computer Science [email protected]


DAVV
SCS

Redirecting Input/Output on UNIX


and DOS Systems
 Standard I/O - keyboard and screen
 Redirect input and output
 Redirect symbol(<)
 Operating system feature, not a C feature
 UNIX and DOS
 $ or % represents command line
 Example:
$ myProgram < input
 Rather than inputting values by hand, read them from a file
 Pipe command(|)
 Output of one program becomes input of another
$ firstProgram | secondProgram
 Output of firstProgram goes to secondProgram

249 [email protected]
DAVV
SCS

Redirecting Input/Output on UNIX


and DOS Systems
 Redirect output (>)
 Determines where output of a program goes
 Example:
$ myProgram > myFile
Output goes into myFile (erases previous contents)
 Append output (>>)
 Add output to end of file (preserve previous contents)
 Example:
$ myOtherProgram >> myFile
Output is added onto the end of myFile

250 [email protected]
DAVV
SCS

The Unconditional Branch: goto


 Unstructured programming
 Use when performance crucial
 break to exit loop instead of waiting until condition becomes false
 goto statement
 Changes flow control to first statement after specified label
 A label is an identifier followed by a colon (i.e. start:)
 Quick escape from deeply nested loop
goto start;

251 [email protected]
DAVV
SCS

Enumeration Constants
 Enumeration
 Set of integer constants represented by identifiers
 Enumeration constants are like symbolic constants whose values are
automatically set
Values start at 0 and are incremented by 1
Values can be set explicitly with =
Need unique constant names
 Example:
enum Months { JAN = 1, FEB, MAR, APR, MAY, JUN, JUL,
AUG, SEP, OCT, NOV, DEC};
Creates a new type enum Months in which the identifiers are set
to the integers 1 to 12
 Enumeration variables can only assume their enumeration constant
values (not the integer representations)

252 [email protected]
Devi Ahilya Vishwavidyalaya

Inline function, Type Qualifiers and Storage


Classes

School of Computer Science [email protected]


DAVV
SCS

Inline Functions
 Recall the two different ways to compute the larger of two integers:
 #define max(a,b) ((a)>(b)? (a):(b))
 int max(int a, int b) { return a>b?a:b; }
 To execute a function call, computer must:
 Save current registers
 Allocate memory on the call stack for the local variables, etc, of the
function being called
 Initialize function parameters
 Jump to the area of memory where the function code is, and jump
back when done

254 [email protected]
DAVV
SCS

Inline Functions
 The macro approach is more efficient since it does not have function call
overhead, but, this approach can be dangerous, as we saw earlier
 Modern C compilers provide inline functions to solve the problem:
 Put the inline keyword before the function header
inline int max(int a, int b) {
return a>b?a:b;
}

255 [email protected]
DAVV
SCS

Inline Functions
 You then use the inline function just like a normal function in your
source code
printf( "%d", max( x, y) );
 When the compiler compiles your program, it will not compile it as a
function; rather, it integrates the necessary code in the line where
max( ) is called, and avoids an actual function call
 The above printf(…) is compiled to be something like:
printf("%d", x>y?x:y);

256 [email protected]
DAVV
SCS

Inline Functions
 Writing the small but often-used functions as inline functions can
improve the speed of your program
 A small problem: You must include the inline function definition (not just
its prototype) before using it in a file
 Therefore, inline functions are often defined in header (.h) files

257 [email protected]
DAVV
SCS

Inline Functions
 Once you include a header file, you can use:
 Inline functions whose definitions are in the header file
 Normal functions whose prototypes are in the header file
 Another minor problem: Some debuggers get confused when handling inline
functions – it may be best to turn functions into inline functions only after
debugging is finished

258 [email protected]
DAVV
SCS

Two advantages and the main disadvantage to inlining

 The inline function is faster. No parameters are pushed on the stack, no


stack frame is created and then destroyed, no branch is made.
 Secondly, the inline function call uses less code!
 The main disadvantage of inlining is that inline code is not linked and
so the code of an inline function must be available to all files that use it.

259 [email protected]
DAVV
SCS

Type Qualifiers

Type qualifiers that control how variables may be accessed or modified

const
Variables of type const may not be changed by your program. The compiler
is free to place variables of this type into read-only memory (ROM).
const int a=10;
creates an integer variable called a with an initial value of 10 that your program may
not modify.
The const qualifier can be used to prevent the object pointed to by an argument to a
function from being modified by that function. That is, when a pointer is passed to a
function, that function can modify the actual object pointed to by the pointer.

260 [email protected]
DAVV
SCS

Volatile
The modifier volatile tells the compiler that a variable's value may be changed in
ways not explicitly specified by the program. For example, a global variable's
address may be passed to the operating system's clock routine and used to hold the
system time. In this situation, the contents of the variable are altered without any
explicit assignment statements in the program. This is important because most C
compilers automatically optimize certain expressions by assuming that a variable's
content is unchanging if it does not occur on the left side of an assignment
statement; thus, it might not be reexamined each time it is referenced.

261 [email protected]
DAVV
SCS

Const + Volatile
You can use const and volatile together. For example, if 0x30 is assumed to
be the value of a port that is changed by external conditions only, the
following declaration would prevent any possibility of accidental side effects:

const volatile char *port = (const volatile char *) 0x30;

262 [email protected]
DAVV
SCS

Storage Class Specifiers


C supports four storage class specifiers:
extern
static
register
Auto

These specifiers tell the compiler how to store the subsequent variable. The
general form of a variable declaration that uses one is shown here:

storage_specifier type var_name;

263 [email protected]
DAVV
SCS

Global Variables
Global variables are known throughout the program and
may be used by any piece of code. Also, they will hold their value throughout
the program's execution. You create global variables by declaring them outside
of any function. Any expression may access them, regardless of what block of
code that expression is in. In the following program, the variable count has been
declared outside of all functions. Although its declaration occurs before the
main( ) function, you could have placed it anywhere before its first use as long
as it was not in a function. However, it is usually best to declare global variables
at the top of the program.

264 [email protected]
DAVV
SCS

Global Variables …..

Storage for global variables is in a fixed region of memory set aside for this
purpose by the compiler. Global variables are helpful when many functions in
your program use the same data. You should avoid using unnecessary global
variables, however. They take up memory the entire time your program is
executing, not just when they are needed.

265 [email protected]
DAVV
SCS

Linkage

C defines three categories of linkage: external, internal, and none. In general,


functions and global variables have external linkage. This means they are
available to all files that constitute a program. File scope objects declared as
static (described in the next section) have internal linkage. These are known
only within the file in which they are declared. Local variables have no linkage
and are therefore known only within their own block.

266 [email protected]
DAVV
SCS

Extern
The principal use of extern is to specify that an object is declared with external
linkage elsewhere in the program.
A declaration declares the name and type of an object. A definition causes
storage to be allocated for the object. The same object may have many
declarations, but there can be only one definition.

In most cases, variable declarations are also definitions. However, by preceding


a variable name with the extern specifier, you can declare a variable without
defining it. Thus, when you need to refer to a variable that is defined in another
part of your program, you can declare that variable using extern.

267 [email protected]
DAVV
SCS

Extern
#include <stdio.h>
int main(void)
{
extern int first, last; /* use global vars */
printf("%d %d", first, last);
return 0;
}
/* global definition of first and last */
int first = 10, last = 20;

268 [email protected]
DAVV
SCS

Multiple-File Programs
An important use of extern relates to multiple-file programs. C allows a program
to be spread across two or more files, compiled separately, and then linked
together. When this is the case, there must be some way of telling all the files
about the global variables required by the program. The best (and most
portable) way to do this is to declare all of your global variables in one file and
use extern declarations in the other.

269 [email protected]
DAVV
SCS

Multiple-File Programs
int x, y; extern int x, y;
char ch; extern char ch;
int main(void) void func22(void)
{ {
/* . . . */ x = y / 10;
} }
void func1(void) void func23(void)
{ {
x = 123; y = 10;
} }

270 [email protected]
DAVV
SCS

Static Variables
Variables declared as static are permanent variables within their own function or
file. Unlike global variables, they are not known outside their function or file, but
they maintain their values between calls. This feature makes them useful when
you write generalized functions and function libraries that other programmers
may use. The static modifier has different effects upon local variables and global
variables.

271 [email protected]
DAVV
SCS

Static Local Variables

When you apply the static modifier to a local variable, the compiler creates
permanent storage for it a static local variable is a local variable that retains its
value Between function calls.

An example of a function that benefits from a static local variable is a number –


series generator that produces a new value based on the previous one.

272 [email protected]
DAVV
SCS

Static Global Variables


Applying the specifier static to a global variable instructs the compiler to create
a global variable known only to the file in which it is declared. Thus, a static
global variable has internal linkage (as described under the extern statement).
This means that even though the variable is global, routines in other files have
no knowledge of it and cannot alter its contents directly, keeping it free from side
effects.

273 [email protected]
DAVV
SCS

Register Variables
The register specifier requested that the compiler keep the value of a variable in
a register of the CPU rather than in memory, where normal variables are stored.
This meant that operations on a register variable could occur much faster than
on a normal variable because the register variable was actually held in the CPU
and did not require a memory access to determine or modify its value.

The register storage specifier originally applied only to variables of type int, char,
or pointer types. type of variable.

274 [email protected]
Devi Ahilya Vishwavidyalaya

Any Questions

School of Computer Science [email protected]

You might also like