1 BASICS FUNCTIONS Notes
1 BASICS FUNCTIONS Notes
Documentation Section
The documentation section consists of a set of comment lines giving the name of the
program, the author and other details, which the programmer would like to use later. There are
two types of comment lines.
1. Block comment lines /* */ and
2. Single line comment lines. //
Link Section
The link section provides instructions to the compiler to link functions from the system
library.
Ex: The statement #include<stdio.h> instructs the compiler to include the file “stdio.h” before
starting the compiling step.
Definition Section
It is used to define symbolic constants and to define macros. The preprocessor directive
#define is used for the purpose.
Ex: # define PI 3.14 assigns the symbolic name PI to the constant value 3.14
There are some variables that are used in more than one function. Such variables are
called global variables and are declared in the global declaration section that is outside of all the
functions. This section also declares all the user-defined functions.
Main( ) Function Section
The main( ) is a special function used by the C system to tell the computer where the
program starts. Every program must have exactly one main function. This section has two parts
a) Declaration part b) Execution part
a) Declaration part: It declares all the variables used in the executable part.
b) Executable part: There is at least one statement in the executable part.
These two parts must appear between the opening and closing braces. The program
execution begins at the opening brace and ends at the closing brace. The closing brace of the
main function is the logical end of the program. All statements in the declaration and executable
part end with a semicolon.
Subprogram Section
This section contains user defined functions that are used in the main function. User
defined functions are generally placed immediately after the main function. All Sections except
the main function section may be absent when they are not required.
1. For Example a ‘C’ program that prints welcome message:
/* A Sample C program */\\
#include<stdio.h>
int main( )
All C Compilers support the following primary (or fundamental or basic) data types namely
integer (int)
floating point (float)
character (char)
A type modifier (qualifier) such as short, long, signed and unsigned when applied to the above
basic types yields additional types.
1. Each of these modifiers (short, long, signed and unsigned) can be applied to the basic
data type int.
2. The modifier signed and unsigned can be applied to the basic data type char.
3. In addition, long can be applied to double.
‘C’ offers three different integer data types. They are short int, int, long int in both signed
and unsigned forms. The difference between these three is the number of bytes to occupy and the
range of values. The size and range of data types on a 16-bit machine are given as follows.
Floating point numbers (real numbers) are defined in „C‟ by the keyword float. ‘C’ offers
different floating point data types. They are float, double and long double.
Character data types
A single character can be defined as a character (char) data type. ‘C’ offers two character
data types. They are signed char and unsigned char
The smallest to the largest data types with respect to size are given as follows:
C-Operators
One of the most important features of C is that it has a very rich set of built in operators
including arithmetic, relational, logical, and bitwise operators.
Assignment Operator
int x ;
x = 20 ;
Some common notation :- lvalue -- left hand side of an assignment operation
rvalue -- right hand side of an assignment operation
Type Conversions :- the value of the right hand side of an assignment is converted to the type
of the lvalue. This may sometimes yield compiler warnings if information is lost in the
conversion.
For Example :-
int x ;
char ch ;
float f ;
Multiple assignments are possible to any degree in C, the assignment operator has right to left
associativity which means that the rightmost expression is evaluated first.
For Example :-
x = y = z = 100 ;
In this case the expression z = 100 is carried out first. This causes the value 100 to be placed in
z with the value of the whole expression being 100 also. This expression value is then taken and
assigned by the next assignment operator on the left i.e. x = y = ( z = 100 ) ;
Arithmetic Operators
+ - * / same rules as mathematics with * and / being evaluated before + and -.
% modulus / remainder operator
For Example :-
int a = 5, b = 2, x ;
float c = 5.0, d = 2.0, f ;
Note that parentheses may be used to clarify or modify the evaluation of expressions of any
type in C in the same way as in normal arithmetic.
For Example :-
x++ ; /* equivalent to x=x+1; */
++ and -- can be used in prefix or postfix notation. In prefix notation the value of the variable is
either incremented or decremented and is then read while in postfix notation the value of the
variable is read first and is then incremented or decremented.
For Example :-
int i, j = 2 ;
These shorthand operators improve the speed of execution as they require the expression, the
variable x in the above example, to be evaluated once rather than twice.
Relational Operators
The full set of relational operators are provided in shorthand notation
> >= < <= == !=
For Example :-
if ( x == 2 )
printf( “x is equal to 2\n” ) ;
Logical Operators
&& -- Logical AND
|| -- Logical OR
! -- Logical NOT
For Example :-
if ( x >= 0 && x < 10 )
printf( “ x is greater than or equal to zero and less than ten.\n” ) ;
Note : There is no Boolean type in C so TRUE and FALSE are deemed to have the following
meanings.
FALSE -- value zero
TRUE -- any non-zero value but 1 in the case of in-built relational operations
For Example :-
2>1 -- TRUE so expression has value 1
2>3 -- FALSE so expression has value 0
i=2>1 ; -- relation is TRUE -- has value 1, i is assigned value 1
Note : Every C expression has a value. Typically we regard expressions like 2 + 3 as the only
expressions with actual numeric values. However the relation 2 > 1 is an expression which
evaluates to TRUE so it has a value 1 in C. Likewise if we have an expression x = 10 this has a
value which in this case is 10 the value actually assigned.
Note : Beware of the following common source of error. If we want to test if a variable has a
particular value we would write for example
if ( x == 10 ) …
But if this is inadvertently written as
if ( x = 10 ) …
this will give no compilation error to warn us but will compile and assign a value 10 to x when
the condition is tested. As this value is non-zero the if condition is deemed true no matter what
value x had originally. Obviously this is possibly a serious logical flaw in a program.
Bitwise Operators
These are special operators that act on char or int arguments only. They allow the
programmer to get closer to the machine level by operating at bit-level in their arguments.
Recall that type char is one byte in size. This means it is made up of 8 distinct bits or binary
digits normally designated as illustrated below with Bit 0 being the Least Significant Bit (LSB)
and Bit 7 being the Most Significant Bit (MSB). The value represented below is 13 in decimal.
RULE : If any two bits in the same bit position are set then the resultant bit in that position is
set otherwise it is zero.
For Example :-
1011 0010 (178)
& 0011 1111 (63)
= 0011 0010 (50)
Bitwise OR, |
RULE : If either bit in corresponding positions are set the resultant bit in that position is set.
For Example :-
1011 0010 (178)
| 0000 1000 (63)
= 1011 1010 (186)
Bitwise XOR, ^
RULE : If the bits in corresponding positions are different then the resultant bit is set.
For Example :-
1011 0010 (178)
^ 0011 1100 (63)
= 1000 1110 (142)
For Example :-
2 << 2 = 8
i.e.
0000 0010 becomes 0000 1000
Ones Complement
RULE : Reverses the state of each bit.
For Example :-
Normally this automatic or implicit casting of operands follows the following guidelines in
ascending order.
long double
double
float
unsigned long
long
unsigned int
signed int
For Example :-
int i ;
float f1, f2 ;
f1 = f2 + i ;
Since f2 is a floating point variable the value contained in the integer variable is temporarily
converted or cast to a floating point variable also to standardise the addition operation in this
case. However it is important to realise that no permanent modification is made to the integer
variable.
Explicit casting coerces the expression to be of specific type and is carried out by means of
the cast operator which has the following syntax.
For Example if we have an integer x, and we wish to use floating point division in the
expression x/2 we might do the following
( float ) x / 2
which causes x to be temporarily cast to a floating point value and then implicit casting causes
the whole operation to be floating point division.
which essentially does the same thing but the former is more obvious and descriptive of what is
happening.
Note : It should be noted that all of these casting operations, both implicit and explicit, require
processor time. Therefore for optimum efficiency the number of conversions should be kept to a
minimum.
Sizeof Operator
The sizeof operator gives the amount of storage, in bytes, associated with a variable or a type
(including aggregate types as we will see later on).
For Example :-
int x , size ;
size = sizeof ( x ) ;
printf(“The integer x requires %d bytes on this machine”, size);
Operato
Description Associativity
r
() Parentheses (function call) (see Note 1) left-to-right
[] Brackets (array subscript)
. Member selection via object name
-> Member selection via pointer
++ -- Postfix increment/decrement (see Note 2)
++ -- Prefix increment/decrement right-to-left
+- Unary plus/minus
!~ Logical negation/bitwise complement
Cast (convert value to temporary value of
(type) type)
* Dereference
& Address (of operand)
Determine size in bytes on this
sizeof implementation
* / % Multiplication/division/modulus left-to-right
+ - Addition/subtraction left-to-right
<< >> Bitwise shift left, Bitwise shift right left-to-right
< <= Relational less than/less than or equal to left-to-right
Relational greater than/greater than or
> >= equal to
== != Relational is equal to/is not equal to left-to-right
& Bitwise AND left-to-right
^ Bitwise exclusive OR left-to-right
| Bitwise inclusive OR left-to-right
&& Logical AND left-to-right
|| Logical OR left-to-right
?: Ternary conditional right-to-left
= Assignment right-to-left
+= -= Addition/subtraction assignment
*= /= Multiplication/division assignment
%= &= Modulus/bitwise AND assignment
Bitwise exclusive/inclusive OR
^= |= assignment
<<= >>= Bitwise shift left/right assignment
, Comma (separate expressions) left-to-right
FUNCTIONS
Definition:- A block of statements that specifies one or more actions to be performed for a
large program. In C, a program is made up of one or more functions, one and only one of
which must be called main. The execution always starts with main.
Example:-
void main() void tax_calculation()
{ {
----------------- …………..
tax_calculation(); }
-------------
}
Components of Function:
Declaration / Prototype
Function Parameters (Actual & Formal)
Function Definition
return Statement
Function call
RECURSION:
A function calling itself is called recursive function. Every recursive function must satisfy two
properties
Base Criteria
Recursive step
Base criteria: There must be certain criteria in recursive function called base criteria in which
the function does not call itself. This criteria is required to exit from that function.
Recursive step: In this condition, each time function call itself but the arguments of the function
must be closer to initial condition.
Example:
int factorial (int n)
{
if (n==0)
Return 1;
else
return (n* factorial(n-1));
}
Activation Records:
An activation record is another name for Stack Frame. It's the data structure that composes a
call stack. It is generally composed of:
Locals to the collie
Return address to the caller
Parameters of the collie
The Call Stack is thus composed of any number of activation records that get added to the stack
as new subroutines are added, and removed from the stack (usually) as they return.
Activation records keep track of values as a program executes. More specifically, an activation
record has a set of names that are bound to values. We link activation records together in two
ways:
with a control link
with an access link
A control link from record A points to the previous record on the stack. The chain of control
links traces the dynamic execution of the program.
An access link from record A points to the record of the closest enclosing block in the program.
The chain of access links traces the static structure (think: scopes) of the program.
STORAGE CLASSES:
auto (default) register static extern
Storage Main memory CPU registers Main memory Main memory
Initial value Garbage Garbage Zero Zero
Keyword auto register static extern
scope Local to block in Local to block Local to the Entire program
which it is defined in which it is block in which it
defined is defined
Life time Till the control Till the control Throughout the Throughout the
remains within the remains within execution of execution of
block in which it the block in program program
is defined which it is
defined
Call by value:
In call-by-value, the argument expression is evaluated, and the resulting value is bound to the
corresponding variable in the function (frequently by copying the value into a new memory
region). In this mechanism a function's argument is evaluated before being passed to the
function.
NOTE: In Pascal, a parameter is passed by value unless the corresponding formal has the
keyword var. Expression can be passed by value but not by reference in Pascal.
In C, parameters are passed by value. If variable is preceded by &, then it is pass by reference.
Expression can be passed by value but not by reference in C.
Example:
procedure swap(x, y: integer);
var
temp: integer;
begin
temp := x;
x:= y;
y := temp;
end;
Call by reference:
In call-by-reference evaluation (also referred to as pass-by-reference), a function receives an
implicit reference to a variable used as argument, rather than a copy of its value. This typically
means that the function can modify the variable used as argument.
Example:
procedure swap(var x, y: integer);
var temp: integer;
begin
temp := x;
x:= y;
y := temp;
end;
Call by copy-restore:
Call-by-copy-restore, copy-in copy-out, call-by-value-result or call-by-value-return is a special
case of call-by-reference. The formal parameter acts as a local variable which is initialized to
the value of the actual parameter. Within the routine, changes to the formal parameter only
affect the local copy. On returning from the routine the final value of the formal parameter is
assigned to the actual parameter.
The semantics of call-by-copy-restore also differ from those of call-by-reference where two or
more function arguments alias one another; that is, point to the same variable in the caller's
environment. Under call-by-reference, writing to one will affect the other; call-by-copy-restore
avoids this by giving the function distinct copies, but leaves the result in the caller's
environment undefined depending on which of the aliased arguments is copied back first.
The result of call by reference and call by copy-restore also differs when there is an exception
during execution of the function. When the reference is passed to the collie uninitialized, this
evaluation strategy may be called call-by-result.
Example:
int y;
procedure calling_procedure
begin
y = 10;
copy_restore(y); //l-value of y is passed
print y; //prints 99
end
procedure copy_restore(x: integer)
begin
x = 99; // y still has value 10 (unaffected)
y = 0; // y is now 0
end
Call by name:
The arguments to a function are not evaluated before the function is called — rather, they are
substituted directly into the function body and then left to be evaluated whenever they appear in
the function. If an argument is not used in the function body, the argument is never evaluated; if
it is used several times, it is re-evaluated each time it appears. If the values of variables in the
expression are changed, the change will be seen immediately (similar to call by reference).
Algol used call by name parameter passing mechanism.
Example:
var i: integer
procedure sum(i,j: integer) : integer
var sm:integer
begin
sm := 0;
for i := 1 to 100 do
sm := sm + j;
sum := sm
end;
begin
print(sum(i, i*10 ))
end
Call by need:
Call-by-need is a memorized version of call-by-name where, if the function argument is
evaluated, that value is stored for subsequent uses. In a "pure" (effect-free) setting, this
produces the same results as call-by-name; when the function argument is used two or more
times, call-by-need is almost always faster.
Static Scope:
Most languages, including Algol, Ada, C, Pascal, Scheme, and Haskell, are statically scoped. A
block defines a new scope. Variables can be declared in that scope, and aren't visible from the
outside. However, variables outside the scope -- in enclosing scopes -- are visible unless they
are overridden. Static scoping is also sometimes called lexical scoping.
Example:
integer m, n;
procedure hardy;
begin
print("in hardy -- n = ", n);
end;
begin
m := 50;
n := 100;
print("in main program -- n = ", n);
laurel(1);
hardy;
end;
The output is:
in main program -- n = 100
in laurel -- m = 50
in laurel -- n = 1
in hardy -- n = 100
in hardy -- n = 100
Dynamic Scope:
Using this scoping rule, we first look for a local definition of a variable. If it isn't found, we
look up the calling stack for a definition. If dynamic scoping were used, the output would be:
in main program -- n = 100
in laurel -- m = 50
in laurel -- n = 1
in hardy -- n = 1
in hardy -- n = 100