Академический Документы
Профессиональный Документы
Культура Документы
Lesson 1:
A Program is defined as a set of instructions executed sequentially. Any language used to
develop programs is called Programming Language. These languages have been broadly
divided into 2 categories High level programming Languages & Low level Programming
Languages. High level languages are the languages which are easily understood by
human beings but are slow at execution. Whereas the low level languages are difficult to
learn but faster at execution. To use the plus points of both these languages C was
designed which is called Middle Level Language.
Now to understand some topics of C like (Bitwise operators) something about the binary
arithmetic must be known as computer stores everything in binary states either 0 or 1.
This System is known as BINARY SYSTEM. Similarly OCTAL SYSTEM and
HEXADECIMAL SYSTEM will be discussed to understand how alphanumeric data is
stored in system.
History of C:
The C programming language was devised in the early 1970s as a system implementation
language for the nascent Unix operating system.
C came into being in the years 1969-1973, in parallel with the early development of the
Unix operating system; the most creative period occurred during 1972. Another spate of
changes peaked between 1977 and 1979, when portability of the Unix system was being
demonstrated. In the middle of this second period, the first widely available description
of the language appeared: The C Programming Language, often called the `white book'
or `K&R' [Kernighan 78]. Finally, in the middle 1980s, the language was officially
standardized by the ANSI X3J11 committee, which made further changes. Until the early
1980s, although compilers existed for a variety of machine architectures and operating
systems, the language was almost exclusively associated with Unix; more recently, its use
has spread much more widely, and today it is among the languages most commonly used
throughout the computer industry.
BCPL, B, and C all fit firmly in the traditional procedural family typified by Fortran and
Algol 60. They are particularly oriented towards system programming, are small and
compactly described, and are amenable to translation by simple compilers. They are
`close to the machine' in that the abstractions they introduce are readily grounded in the
concrete data types and operations supplied by conventional computers, and they rely on
library routines for input-output and other interactions with an operating system. With
less success, they also use library procedures to specify interesting control constructs
such as coroutines and procedure closures.
Lesson 2:
Standardization
By 1982 it was clear that C needed formal standardization. The best approximation to a
standard, the first edition of K&R, no longer described the language in actual use; in
particular, it mentioned neither the void or enum types. While it foreshadowed the newer
approach to structures, only after it was published did the language support assigning
them, passing them to and from functions, and associating the names of members firmly
with the structure or union containing them. Although compilers distributed by AT&T
incorporated these changes, and most of the purveyors of compilers not based on pcc
quickly picked up them up, there remained no complete, authoritative description of the
language.
Octal is base 8.
Base 8 is where the only numbers you can use are zero thru to seven. ie:
the decimal value for 1 is represented in octal as 1 but the octal value of
8 (Decimal) is shown as 10 the value of 9 (Decimal) is 11 in octal.
• A-Z
• a -z
• 0-9
• space . , : ; ' $ "
• # % & ! _ {} [] () < > |
• +-/*=
The use of most of this set of characters will be discussed throughout the course.
C makes use of only 32 keywords which combine with the formal syntax to the form the
C programming language. Note that all keywords are written in lower case - C, like
UNIX, uses upper and lowercase text to mean different things. If you are not sure what to
use then always use lowercase text in writing your C programs. A keyword may not be
used for any other purposes. For example, you cannot have a variable called auto.
Lesson 4:
pre-processor directives
global declarations
main()
{
local variables to function main ;
statements associated with function main ;
}
f1()
{
local variables to function 1 ;
statements associated with function 1 ;
}
f2()
{
local variables to function f2 ;
statements associated with function 2 ;
}
.
.
.
etc
Note the use of the bracket set () and {}. () are used in conjunction with function names
whereas {} are used as to delimit the C statements that are associated with that function.
Also note the semicolon - yes it is there, but you might have missed it! a semicolon (;) is
used to terminate C statements. C is a free format language and long statements can be
continued, without truncation, onto the next line. The semicolon informs the C compiler
that the end of the statement has been reached. Free format also means that you can add
as many spaces as you like to improve the look of your programs.
LESSON 5:
This instruction is used to declare the type of variables being used in the program. A
variable is a location in RAM (main memory) for temporary storage of intermediate data.
Any variable used in the program must be declared before using it in any statement. The
type declaration statement is written at the beginning of main() function.
i) While declaring the type of variable we can also initialize it as shown below:
int i=10,j=20;
is same as
int j=20, i=10;
However,
is not.this is because here we are trying to use a even before defining it.
iii) Similarly
int a,b,c,d;
a=b=c=10;
is O.K. but
int a=b=c=d=10;
will not work.( find out why ???)
LESSON 6:
ARITHMETIC INSTRUCTIONS:
A C arithmetic instruction consists of a variable name on the left hand side of = and
variable names & constants on the right han side of =. The variables & constants on the
right hand side of = are connected by arithmetic operators like + , -, *, /.
Exa:
int ad;
float kot, deta,alpha, beta, gamma;
ad=3200;
koi=0.0056;
.
.
.
.
.
deta= alpha* beta / gamma +3.2 * 2/5;
here
The variables & constants together are called OPERANDS that are operated upon
by the arithmetic operators and the result is assigned using the assignment operator, to the
variable on the left hand side.
LESSON 7:
HIERARCHY OF OPEATIONS:
_________________________________________________________________
_
PRIORITY OPERATORS DESCRIPTION
_________________________________________________________________
_
3rd = assignment
________________________________________________________________
Few Tips:
a) Within parentheses the same hierarchy is operatie. Also if there are more than
set of parentheses, the operations within the innermost parentheses would be
performed first, followed by the operations within the second innermost
parentheses & so on.
CONTROL INSTRUCTIONS IN C:
They enable us to specify the order in which the various instructions in a program
are to be executed by the computer. They determine the “flow of control” in a
program.
Sequence Control Instruction ensures that the instructions are executed in the
same order in which they appear in a program.
Case Control Instruction allows user to take the work of multiple ifs using
different cases.
Each of these types with enough examples will be discussed in detail during the
class.
LESSON 9:
if (temperature < 0)
print("Frozen\n");
Loops
C gives you a choice of three types of loop, while, do while and for.
• The while loop keeps repeating an action until an associated test returns
false. This is useful where the programmer does not know in advance how
many times the loop will be traversed.
• The do while loops is similar, but the test occurs after the loop body is
executed. This ensures that the loop body is run at least once.
• The for loop is frequently used, usually where the loop will be traversed a
fixed number of times. It is very flexible, and novice programmers should
take care not to abuse the power it offers.
The while loop is used to look at the characters in the string one at a time until the
null character is found. Then the loop is exited and the index of the null is
returned. While the character isn't null, the index is incremented and the test is
repeated.
LESSON 11:
• The first is run before the loop is entered. This is usually the initialisation
of the loop variable.
• The second is a test, the loop is exited when this returns false.
• The third is a statement to be run every time the loop body is completed.
This is usually an increment of the loop counter.
The example is a function which calculates the average of the numbers stored in
an array. The function takes the array and the number of elements as arguments.
float average(float array[], int count)
{ float total = 0.0;
int i;
return(total / count);
}
The for loop ensures that the correct number of array elements are added up
before calculating the average.
The three statements at the head of a for loop usually do just one thing each,
however any of them can be left blank. A blank first or last statement will mean
no initialisation or running increment. A blank comparison statement will always
be treated as true. This will cause the loop to run indefinitely unless interrupted by
some other means. This might be a return or a break statement.
It is also possible to squeeze several statements into the first or third position,
separating them with commas. This allows a loop with more than one controlling
variable. The example below illustrates the definition of such a loop, with
variables hi and lo starting at 100 and 0 respectively and converging.
The for loop is extremely flexible and allows many types of program
behaviour to be specified simply and quickly.
LESSON 12:
• Only one variable is tested, all branches must depend on the value of that
variable. The variable must be an integral type. (int, long, short or char).
• Each possible value of the variable can control a single branch. A final, catch
all, default branch may optionally be used to trap all unspecified cases.
estimate(number)
int number;
/* Estimate a number as none, one, two, several, many */
{ switch(number) {
case 0 :
printf("None\n");
break;
case 1 :
printf("One\n");
break;
case 2 :
printf("Two\n");
break;
case 3 :
case 4 :
case 5 :
printf("Several\n");
break;
default :
printf("Many\n");
break;
}
}
Each interesting case is listed with a corresponding action. The break statement prevents
any further statements from being executed by leaving the switch. Since case 3 and case 4
have no following break, they continue on allowing the same action for several values of
number.
Both if and switch constructs allow the programmer to make a selection from a number
of possible actions.
The other main type of control statement is the loop. Loops allow a statement, or block of
statements, to be repeated. Computers are very good at repeating simple tasks many
times, the loop is C's way of achieving this.
LESSON 14:
ANSI C
The American National Standards Institute defined a standard for C,
eliminating much uncertainty about the exact syntax of the language. This
newcomer, called ANSI C, proclaims itself the standard version of the language.
As such it will inevitably overtake, and eventually replace common C.
ANSI C does incorporate a few improvements over the old common C. The main
difference is in the grammar of the language. The form of function declarations
has been changed making them rather more like Pascal procedures.
This course introduces ANSI C since it is supported by the SUN workstation
compilers. Most C programming texts are now available in ANSI editions.
prints the words on the screen. The text to be printed is enclosed in double quotes.
The \n at the end of the text tells the program to print a newline as part of the
output.
Most C programs are in lower case letters. You will usually find upper case letters
used in preprocessor definitions (which will be discussed later) or inside quotes as
parts of character strings. C is case sensitive, that is, it recognises a lower case
letter and it's upper case equivalent as being different.
LESSON 15:
BEWARE: In C Array subscripts start at 0 and end one less than the array size.
For example, in the above case valid subscripts range from 0 to 49. This is a BIG
difference between C and other languages and does require a bit of practice to get
in the right frame of mind.
In C, arrays and pointers are closely related; a discussion of one usually refers to
the other.
type var_name[size];
In C, all arrays have zero as the index of their first element. Therefore a
declaration of char p[10]; declares a ten-element array (p[0] through p[9]).
LESSON 16:
p = sample;
The address of the first element may also be specified using the & operator. For
example, sample and &sample[0] produce the same result. The former is usually
used.
Strings
A string is actually an array of characters. Because strings are terminated by a null
('\0'), character arrays must be declared with one extra element (to hold the null).
Although C does not have a string data type, it allows string constants. For
example, "hello there" is a string constant.
C supports a wide range of string manipulation functions, including:
Function Description
strcpy(s1,s2) Copies s2 into s1.
Since strcmp() returns false if the strings are equal, it is best to use the !
operator to reverse the condition if the test is for equality.
LESSON 17:
Two-Dimensional Arrays
function(int x[][20]
Arrays of Strings
Arrays of strings are created using a two-dimensional array. The left index
determines the number of strings. Each string is accessed using only the left index
(eg, gets(array[2] accesses the third string).
Multi-Dimensional Arrays
C allows arrays of more than two dimensions, the exact limit depending on the
individual compiler.
LESSON 18:
Array Initialization
Arrays may be initialized at the time of declaration. The following example
initializes a ten-element integer array:
int i[10] = { 1,2,3,4,5,6,7,8,9,10 };
Character arrays which hold strings allow a shorthand initialization, e.g.:
char str[9] = "I like C";
which is the same as:
char str[9] = { 'I',' ','l','i','k','e',' ','C','\0' };
When the string constant method is used, the compiler automatically supplies the
null terminator.
Multi-dimensional arrays are initialized in the same way as single-dimension
arrays, e.g.:
int sgrs[6][2] =
{
1,1,
2,4,
3,9,
4,16,
5,25
6,36
};
LESSON 19:
Pointers :
• Arrays,
• Structures,
• Functions.
NOTE: Pointers are perhaps the most difficult part of C to understand. C's
implementation is slightly different DIFFERENT from other languages.
What is a Pointer?
int *pointer;
NOTE: We must associate a pointer to a particular type: You can't assign the
address of a short int to a long int, for instance.
LESSON 20:
(Pointers Contd..)
Consider the effect of the following code:
int x = 1, y = 2;
int *ip;
ip = &x;
y = *ip;
x = ip;
*ip = 3;
Fig. 9.1 Pointer, Variables and Memory Now the assignments x = 1 and y = 2
obviously load these values into the variables. ip is declared to be a pointer to an
integer and is assigned to the address of x (&x). So it gets loaded with the value 100.
IMPORTANT: When a pointer is declared it does not point anywhere. You must
set it to point somewhere before you use it.
So ...
int *ip;
*ip = 100;
will generate an error (program crash!!).
The correct use is:
int *ip;
int x;
ip = &x;
*ip = 100;
LESSON 21:
int a[10], x;
int *pa;
pa = &a[0]; /* pa pointer to address of a[0] */
x = *pa;
/* x = contents of pa (a[0] in this case) */
To get somewhere in the array (Fig. 9.3) using a pointer we could do:
pa + i a[i]
WARNING: There is no bound checking of arrays and pointers so you can easily
go beyond array memory and overwrite other things.
C however is much more subtle in its link between arrays and pointers.
For example we can just type
pa = a;
instead of
pa = &a[0]
and
a[i] can be written as *(a + i).
i.e. &a[i] a + i.
We also express pointer addressing like this:
pa[i] *(pa + i).
LESSON 22:
How useful are pointers for scientific programming? Probably much less than
C fans think, few algorithms used in scientific require pointers. It is well-
known that having unrestricted pointers in a programming language makes it
difficult for the compiler to generate efficient code.
C pointers are characterized by their value and data-type. The value is the
address of the memory location the pointer points to, the type determines how
the pointer will be incremented/decremented in pointer (or subscript)
arithmetic (see below).
For example, a 4x3 array of T (where "T" is some data type) may be declared
by: "T mat[4][3]", and described by the following scheme:
+-----+-----+-----+
mat == mat[0] ---> | a00 | a01 | a02 |
+-----+-----+-----+
+-----+-----+-----+
mat[1] ---> | a10 | a11 | a12 |
+-----+-----+-----+
+-----+-----+-----+
mat[2] ---> | a20 | a21 | a22 |
+-----+-----+-----+
+-----+-----+-----+
mat[3] ---> | a30 | a31 | a32 |
+-----+-----+-----+
LESSON 23:
The array elements are stored in memory row after row, so the array equation
for element "mat[m][n]" of type T is:
address(mat[i][j]) = address(mat[0][0]) + (i * n + j) * size(T)
address(mat[i][j]) = address(mat[0][0]) +
i * n * size(T) +
j * size(T)
address(mat[i][j]) = address(mat[0][0]) +
i * size(row of T) +
j * size(T)
A few remarks:
2) Note that it's more efficient to compute the array equation "iteratively"
- not using the distributive law to eliminate the parentheses (just count the
arithmetical operations in the first two versions of the array equation above).
The K&R method (see below) works iteratively.
a * x**2 + b * x + c = (a * x + b) * x + c
4) The number of rows doesn't enter into the array equation, you don't
need it to compute the address of an element. That is the reason you don't
have to specify the first dimension in a routine that is being passed a
2Darray, just like in Fortran's assumed-size arrays.
LESSON 24:
The decay convention shouldn't be applied more than once to the same
object.
xxx[i] = *(xxx # i)
When rule #4 + rule #3 are applied recursively (this is the case of a multi-
dimensional array), only the data type is dereferenced and not the pointer's
value, except on the last step.
LESSON 25:
"mat" is clearly a "2D array of T" and decays by rule #3 into a "pointer to a
row of T". So we get the first two terms of the array equation.
We have now one pointer addition left, using again the "decay convention",
the 1D array "row of T" becomes a pointer to its first element, i.e.
"pointer to T". We perform the pointer addition, and get the third term
of the array equation:
LESSON 26:
ptr2 = &ptr1;
ptr1 = (type *)mat;
but that wouldn't work either, the information on the array "width" (n), is lost,
and we would get right only the first row, then we will have again wild memory
accesses.
LESSON 27:
An example program:
include <stdio.h>
include <stdlib.h>
main()
{
long mat[5][5], **ptr;
mat[0][0] = 3;
ptr = (long **)mat;
return;
}
mat 7FDF6310
ptr 7FDF6310
mat[0][0] 3
&mat[0][0] 7FDF6310
&ptr[0][0] 3
LESSON 28:
Functions in C
return(ret_val);
}
The function follows a simple algorithm, multiplying the value by itself
pow times. A for loop is used to control the number of multiplications, and
variable ret_val stores the value to be returned.
The body of the function is bounded by a set of curly brackets. Any variables
declared here will be treated as local unless specifically declared as static or
extern types.
return(ret_val);
On reaching a return statement, control of the program returns to the calling
function. The bracketed value is the value which is returned from the function. If
the final closing curly bracket is reached before any return value, then the
function will return automatically, any return value will then be meaningless.
The example function can be called by a line in another function which looks like
this
result = power(val, pow);
This calls the function power assigning the return value to variable result.
The definition uses type void which is optional. It shows that no return value is
used. Otherwise the function is much the same as the previous example, except
that there is no return statement. Some void type functions might use return, but
only to force an early exit from the function, and not to return any value. This is
rather like using break to jump out of a loop.
LESSON 29:
LESSON 30:
Function Prototypes:
The prototype has the same form as the function definition, except that it
is terminated by a semicolon immediately following the closing parenthesis and
therefore has no body. In either case, the return type must agree with the return
type specified in the function definition.
i) They establish the return type for functions that return types other than int.
Although functions that return int values do not require prototypes, prototypes
are recommended.
iv) The parameter list is used for checking the correspondence of arguments in
the function call with the parameters in the function definition.
A prototype establishes the attributes of a function so that calls to the function that
precede its definition (or occur in other source files) can be checked for argument-
type and return-type mismatches.
LESSON 31:
There are many cases when we may want to alter a passed argument in the
function and receive the new value back once to function has finished. Other
languages do this (e.g. var parameters in PASCAL). C uses pointers explicitly to
do this. Other languages mask the fact that pointers also underpin the
implementation of this.
The best way to study this is to look at an example where we must be able to
receive changed parameters.
Pointers provide the solution: Pass the address of the variables to the functions
and access address of function.
Thus our function call in our program would look like this:
swap(&a, &b)
LESSON 32:
int *x;
*x = 100;
x = &y;
*x = 100;
This may be hard to spot. NO COMPILER ERROR. Also x could some random
address at initialisation.
Illegal indirection
Suppose we have a function malloc() which tries to allocate memory dynamically
(at run time) and returns a pointer to block of memory requested if successful or a
NULL pointer otherwise.
No * in
*p = (char *) malloc(100);
Malloc returns a pointer. Also p does not point to any address.
The correct code should be:
p = (char *) malloc(100);
p = (char *) malloc(100);
if ( p == NULL)
Write a program to find the number of times that a given word(i.e. a short string)
occurs in a sentence (i.e. a long string!).
Read data from standard input. The first line is a single word, which is
followed by general text on the second line. Read both up to a newline
character, and insert a terminating null before processing.
Write a program that takes three variable (a, b, b) in as separate parameters and
rotates the values stored so that value a goes to be, b, to c and c to a.
LESSON 33:
The C Preprocessor
The C preprocessor is a tool which filters your source code before it is compiled. The
preprocessor allows constants to be named using the #define notation. The preprocessor
provides several other facilities which will be described here. It is particularly useful for
selecting machine dependent pieces of code for different computer types, allowing a
single program to be compiled and run on several different computers.
The C preprocessor isn't restricted to use with C programs, and programmers who use
other languages may also find it useful, however it is tuned to recognise features of the C
language like comments and strings, so its use may be restricted in other circu mstances.
The preprocessor is called cpp, however it is called automatically by the compiler so you
will not need to call it while programming in C.
This will lead to the value 256 being substituted for each occurrence of the word
MAXSIZE in the file.
#define can also be given arguments which are used in its replacement. The definitions
are then called macros. Macros work rather like functions, but with the following minor
differences.
Macros are full of traps for the unwary programmer. In particular the textual substitution
means that arithmetic expressions are liable to be corrupted by the order of evaluation
rules.
Here is an example of a macro which won't work.
a = DOUBLE(b) * c;
This will be expanded to
a = b+b * c;
And since * has a higher priority than +, the compiler will treat it as.
a = b + (b * c);
The problem can be solved using a more robust definition of DOUBLE
LESSON 34:
Another use for #include for the programmer is where multi-file programs are being
written. Certain information is required at the beginning of each program file. This can be
put into a file called globals.h and included in each program file. Local header file names
are usually enclosed by double quotes, " ". It is conventional to give header files a name
which ends in .h to distinguish them from other types of file.
The preprocessor has a conditional statement similar to C's if else. It can be used to
selectively include statements in a program. This is often used where two different
computer types implement a feature in different ways. It allows the programmer to
produce a program which will run on either type.
The keywords for conditional selection are; #ifdef, #else and #endif.
#ifdef
takes a name as an argument, and returns true if the the name has a current
definition. The name may be defined using a #define, the -d option of the
compiler, or certain names which are automatically defined by the UNIX
environment.
#else
is optional and ends the block beginning with #ifdef. It is used to create a 2 way
optional selection.
#endif
ends the block started by #ifdef or #else.
Where the #ifdef is true, statements between it and a following #else or #endif are
included in the program. Where it is false, and there is a following #else, statements
between the #else and the following #endif are included.