C Notes
C Notes
Definition of terms
Computer Program:
A computer program is a set of coded instructions given to the computer, and represents a logical
solution to a problem. It directs a computer in performing various operations/tasks on the data
supplied to it.
Programming:
Programming is the process of designing a set of instructions (computer programs) which can be
used to perform a particular task or solve a specific problem.
It involves use of special characters, signs and symbols found in a particular programming language
to create computer instructions.
Programming Languages:
Object code (object program)- Refers to the program code that is in machine-readable (binary)
form. It is produced by a Compiler or Assembler after translating the Source program into a form
that can be readily loaded into the computer.
LANGUAGE TRANSLATORS
A computer uses & stores information in binary form, and therefore, it cannot understand programs
written in either high-level or low-level languages. This means that, any program code written in
Assembly language or high-level language must be translated into Machine language, before the
computer can recognize & run these programs.
A Translator is special system software used to convert the Source codes (program statements
written in any of the computer programming languages) to their Object codes (computer language
equivalents).
The Translators reside in the main memory of the computer, and use the program code of the high-
level or Assembly language as input data, changes the codes, and gives the output program in
machine-readable code.
In addition, translators check for & identify some types of errors (e.g., Syntax/grammatical errors)
that may be present in the program being translated. They will produce error messages if there is a
mistake in the code.
Each language needs its own translator. Generally, there are 3 types of language translators:
1. Assembler.
2. Interpreter.
3. Compiler.
Note. Interpreters & Compilers translate source programs written in high-level languages to their
machine language equivalents.
Assembler
An assembler translates programs written in Assembly language into machine language that the
computer can understand and execute.
Functions of an Assembler.
1). It checks whether the instructions written are valid, and identifies any errors in the program.
The Assembler will display these errors as well as the complete source and object programs.
If the program has no errors, the job control will let it run immediately, or save the object
program so that it may run it later without translating it again.
E.g., the Assembler keeps a table of these names so that if an instruction refers to it, the
Assembler can easily tell the location to which it was assigned.
Usually, the Assembler generates a machine code only when no errors are detected. Some of
the errors include;
- Typing mistakes.
- Using the wrong format for an instruction.
- Specifying a memory location outside the range 0 – 2047.
Note. The Assembler cannot detect Logic errors. The programmer knows of these errors
only when the program is run & the results produced are incorrect (not what the programmer
expected). The programmer must therefore, go through the program & try to discover why an
incorrect result was being produced.
Interpreter
An interpreter translates a source program word by word or line by line. This allows the CPU to
execute one line at a time.
The translated line is not stored in the computer memory. Therefore, every time the program is
needed for execution, it has to be translated.
Compiler
A compiler translates the entire/whole source program into object code at once, and then executes it
in machine language code. These machine code instructions can then be run on the computer to
perform the particular task as specified in the high-level program.
The process of translating a program written in a high-level source language into machine language
using a compiler is called Compilation.
Functions of a compiler.
1). It identifies the proper order of processing, so as to execute the process as fast as possible &
minimize the storage space required in memory.
2). It allocates space in memory for the storage locations defined in the program to be executed.
3). It reads each line of the source program & converts it into machine language.
4). It checks for Syntax errors in a program (i.e., statements which do not conform to the
grammatical rules of the language). If there are no syntax errors, it generates machine code
equivalent to the given program.
5). It combines the program (machine) code generated with the appropriate subroutines from the
library.
6). It produces a listing of the program, indicating errors, if any.
Interpreter Compiler
1. Translates & executes each statement of 1. Translates all the source code statements at once
the source code one at a time. as a unit into their corresponding object codes,
before the computer can execute them.
The source code instruction is translated
& immediately obeyed by the computer A Compiler translates the entire source program
hardware before the next instruction can first to machine code, and then the code is
be translated. executed by the CPU.
(Translation & execution go together). (Translation & execution are separate phases)
2. Translates the program each time it is
needed for execution; hence, it is slower 2. Compiled programs (object codes) can be saved
than compiling. on a storage media and run when required; hence
3. Interpreted object codes take less executes faster than interpreted programs.
memory compared to compiled
programs. 3. Compiled programs require more memory as
their object files are larger.
4. For an Interpreter, the syntax
(grammatical) errors are reported & 4. For a Compiler, the syntax errors are reported &
corrected before the execution can corrected after the source code has been
continue. translated to its object code equivalent.
5. An Interpreter can relate error messages
to the source program, which is always 5. Once the source program has been translated, it is
available to the Interpreter. This makes no longer available to the Compiler, so the error
debugging of a program easier when messages are usually less meaningful.
using an Interpreter than a Compiler.
Computer programs are usually developed in Modules or Subroutines (i.e., program segments
meant to carry out the specific relevant tasks). During program translation, these modules are
translated separately into their object (machine) code equivalents.
The Linker is a utility software that accepts the separately translated program modules as its input,
and logically combines them into one logical module, known as the Load Module that has got all
the required bits and pieces for the translated program to be obeyed by the computer hardware.
The Loader is a utility program that transfers the load module (i.e. the linker output) into the
computer memory, ready for it to be executed by the computer hardware.
Syntax
The term Syntax refers to the grammatical rules, which govern how words, symbols, expressions
and statements may be formed & combined.
Semantics
These are rules, which govern the meaning of syntax. They dictate what happens (takes place)
when a program is run or executed.
There are many programming languages. The languages are classified into 2 major categories:
Each programming language has its own grammatical (syntax) rules, which must be obeyed in order
to write valid programs, just as a natural language has its own rules for forming sentences.
LOW-LEVEL LANGUAGES
These are the basic programming languages, which can easily be understood by the computer
directly, or which require little effort to be translated into computer understandable form.
They include:
1. Machine languages.
2. Assembly languages.
Machine language is written using machine codes (binary digits) that consist of 0’s & 1’s.
Different CPU’s have different machine codes, e.g., codes written for the Intel Pentium processors
may differ from those written for Motorola or Cyrix processors. Therefore, before interpreting the
meaning of a particular code, a programmer must know for which CPU the program was written.
It specifies the location (address) of the computer memory where the data to be worked upon
can be found.
It states to the Control Unit of the CPU what operation should be performed on the data/item
held in the address, e.g., Addition, Subtraction, Division, Multiplication, etc.
Assembly languages were developed in order to speed up programming (i.e., to overcome the
difficulties of understanding and using machine languages).
To write program statements in Assembly language, the programmer uses a set of symbolic
operation codes called Mnemonic codes.
The code could be a 2 or 3 shortened letter word that will cause the computer to perform specific
operation. E.g., MOV – move, ADD - addition, SUB – subtraction, RD - read.
Example;
RD PAT, 15 (read the value 15 stored in the processor register named PAT)
SUB PAT, 10 (subtract 10 from the value in register PAT)
They are therefore suitable for writing Operating system software & Game programs, which
require fast & efficient use of the CPU time.
Very few computer programs are actually written in machine or Assembly language because of the
following reasons;
1. Low-level languages are difficult to learn, understand, and write programs in them.
2. Low-level language programs are difficult to debug (remove errors from).
3. Low-level languages have a collection of very detailed & complex instructions that control the
internal circuiting of the computer. Therefore, it requires one to understand how the computer
codes internally.
4. Relating the program & the problem structures is difficult, and therefore cumbersome to work
with.
5. The programs are very long; hence, writing a program in a low-level language is usually tedious
& time consuming.
6. The programs are difficult to develop, maintain, and are also prone to errors (i.e., it requires
highly trained experts to develop and maintain the programs).
This implies that, they are designed for a specific machine & specific processor, and therefore,
cannot be transferred between machines with different hardware or software specifications.
8. It is not easy to revise the program, because this will mean re-writing the program again.
HIGH-LEVEL PROGRAMMING LANGUAGES
High-level languages were developed to solve (overcome) the problems encountered in low-level
programming languages.
They contain statements that have an extensive vocabulary of words, symbols, sentences &
mathematical expressions, which are very similar to the normal English language.
1. To improve the productivity of a programmer. This is because; the source programs of high-
level languages are shorter than the source programs of low-level languages, since one
statement translates into several machine code instructions.
2. To ease the training of new programmers, since there is no need to learn the detailed layout of a
procession/sequence.
1. They are easily portable, i.e., they can be transferred between computers of different families
and run with little or no modification.
2. High-level language programs are short, and take shorter time to be translated.
5. High level language programs are easy to modify, and also to incorporate additional features
thus enhancing its functional capabilities.
6. They are ‘user-friendly’ & problem-oriented; hence, can be used to solve problems arising from
the real world.
7. They enable programmers to adapt easily to new hardware. This is because; they don’t have to
worry about the hardware design of the computer.
8. High-level language programs are self-documenting, i.e., the program statements displays the
transparency of purpose making the verification of the program easy.
9. High level languages are more flexible; hence, they enhance the creativity of the programmer
and increase his/her productivity in the workplace.
1. High-level languages are not machine-oriented; hence, they do not use of the CPU and hardware
facilities efficiently.
2. The languages are machine-independent, and cannot be used in programming the hardware
directly.
3. Each high-level language statement converts into several machine code instructions. This
means that, they use more storage space, and it also takes more time to run the program.
4. Their program statements are too general; hence, they execute slowly than their machine code
program equivalents.
5. They have to be interpreted or compiled to machine-readable form before the computer can
execute them.
The source program written in a high-level language needs a Compiler, which is loaded into the
main memory of the computer, and thus occupies much of memory space. This greatly reduces
the memory available for a source program.
STRUCTURED LANGUAGES
A structured (procedural) language allows a large program to be broken into smaller sub-programs
called modules, each performing a particular (single) task. This technique of program design is
referred to as structured programming.
Structured programming also makes use of a few simple control structures in problem solving. The
3 basic control structures are:
Sequence
Selection.
Iteration (looping).
1. It is flexible.
2. Structured programs are easier to read.
3. Programs are easy to modify because; a programmer can change the details of a section without
affecting the rest of the program.
4. It is easier to document specific tasks.
5. Use of modules that contain standard procedures throughout the program saves development
time.
6. Modules can be named in such a way that, they are consistent and easy to find in
documentation.
7. Debugging is easier because; each module can be designed, coded & tested independently.
Before we study the basic building blocks of the C programming language, let us look at a bare
minimum C program structure so that we can take it as a reference in the upcoming chapters.
Preprocessor Commands
Functions
Variables
Statements & Expressions
Comments
Let us look at a simple code that would print the words "Hello World" −
Live Demo
#include <stdio.h>
int main() {
/* my first program in C */
printf("Hello, World! \n");
return 0;
}
Let us take a look at the various parts of the above program −
The first line of the program #include <stdio.h> is a preprocessor command, which tells a C
compiler to include stdio.h file before going to actual compilation.
The next line int main() is the main function where the program execution begins.
The next line /*...*/ will be ignored by the compiler and it has been put to add additional
comments in the program. So such lines are called comments in the program.
The next line printf(...) is another function available in C which causes the message "Hello,
World!" to be displayed on the screen.
The next line return 0; terminates the main() function and returns the value 0.
Let us see how to save the source code in a file, and how to compile and run it. Following are the
simple steps −
Open a text editor and add the above-mentioned code.
Save the file as hello.c
Open a command prompt and go to the directory where you have saved the file.
Type gcc hello.c and press enter to compile your code.
If there are no errors in your code, the command prompt will take you to the next line and
would generate a.out executable file.
Now, type a.out to execute your program.
You will see the output "Hello World" printed on the screen.
$ gcc hello.c
Program Design
Program design is the foundation for a good program and is therefore an important part of the
program development cycle. Before coding a program, the program should be well conceived and
all aspects of the program design should be considered in detail.
Program design is basically concerned with the development of a strategy to be used in writing the
program, in order to achieve the solution of a problem. This includes mapping out a solution
procedure and the form the program would take. The program design involves the following four
stages:
1. Problem analysis.
2. Outlining the program structure.
3. Algorithm development.
4. Selection of control structures.
Problem Analysis
Before we think of a solution procedure to the problem, we must fully understand the nature of the
problem and what we want the program to do. Without the comprehension and definition of the
problem at hand, program design might turn into a hit or miss approach. We must carefully decide
the following at this stage;
An important feature of this approach is that at each level, the details of the design of lower levels
are hidden. The higher level functions are designed first, assuming certain broad tasks of the
immediately lower level functions. The actual details of the lower level functions are not considered
until that level is reached. Thus the design of functions proceeds from top to bottom, introducing
progressively more and more refinements.
This approach will produce a readable and modular code that can be easily understood and
maintained. It also helps us classify the overall functioning of the program in terms of lower level
functions.
Algorithm Development
After we have decided a solution procedure and an overall outline of the program, the next step is to
work a out a detailed definite, step by step procedure, known as algorithm for each function. The
most common method of describing an algorithm is through the use of flowcharts. The other
method is to write what is known as pseudocode. The flow chart presents the algorithm pictorially,
while the pseudocode describe the solution steps in a logical order. Either method involves concepts
of logic and creativity.
Since algorithm is the key factor for developing an efficient program, we should devote enough
attention to this step. A problem might have many different approaches to its solution. For example,
there are many sorting techniques available to sort a list. Similarly, there are many methods of
finding and select the one, which is simple the area under a curve. We must consider all possible
approaches to follow, takes less execution time, and produces results with the required accuracy.
Sequence structure denotes the execution of statements sequentially one after another. Selection
structure involves a decision, based on a condition and may have two or more branches, which
usually join again at a later point. if …else and switch statements in C can be used to implement a
selection structure. Looping structure is used when a set of instructions is evaluated repeatedly. This
structure can be
Data types in c refer to an extensive system used for declaring variables or functions of different
types. The type of a variable determines how much space it occupies in storage and how the bit
pattern stored is interpreted.
The types in C can be classified as follows −
1 Basic Types
They are arithmetic types and are further classified into: (a) integer types and (b) floating-
point types.
2 Enumerated types
They are again arithmetic types and they are used to define variables that can only assign
certain discrete integer values throughout the program.
4 Derived types
They include (a) Pointer types, (b) Array types, (c) Structure types, (d) Union types and
(e) Function types.
The array types and structure types are referred collectively as the aggregate types. The type of a
function specifies the type of the function's return value. We will see the basic types in the
following section, where as other types will be covered in the upcoming chapters.
Integer Types
The following table provides the details of standard integer types with their storage sizes and value
ranges −
Floating-Point Types
The following table provide the details of standard floating-point types with storage sizes and
value ranges and their precision −
The header file float.h defines macros that allow you to use these values and other details about the
binary representation of real numbers in your programs. The following example prints the storage
The void type specifies that no value is available. It is used in three kinds of situations −
3 Pointers to void
A pointer of type void * represents the address of an object, but not its type. For example,
a memory allocation function void *malloc( size_t size ); returns a pointer to void which
can be casted to any data type.
C Identifiers
C identifiers represent the name in the C program, for example, variables, functions, arrays,
structures, unions, labels, etc. An identifier can be composed of letters such as uppercase, lowercase
letters, underscore, digits, but the starting letter should be either an alphabet or an underscore. If the
identifier is not used in the external linkage, then it is called as an internal identifier. If the identifier
is used in the external linkage, then it is called as an external identifier.
We can say that an identifier is a collection of alphanumeric characters that begins either with an
alphabetical character or an underscore, which are used to represent various programming elements
such as variables, functions, arrays, structures, unions, labels, etc. There are 52 alphabetical
characters (uppercase and lowercase), underscore character, and ten numerical digits (0-9) that
represent the identifiers. There is a total of 63 alphanumerical characters that represent the
identifiers.
o The first character of an identifier should be either an alphabet or an underscore, and then it
can be followed by any of the character, digit, or underscore.
o It should not begin with any numerical digit.
o In identifiers, both uppercase and lowercase letters are distinct. Therefore, we can say that
identifiers are case sensitive.
o Commas or blank spaces cannot be specified within an identifier.
o Keywords cannot be represented as an identifier.
o The length of the identifiers should not be more than 31 characters.
o Identifiers should be written in such a way that it is meaningful, short, and easy to read.
Types of identifiers
o Internal identifier
o External identifier
Internal Identifier
If the identifier is not used in the external linkage, then it is known as an internal identifier. The
internal identifiers can be local variables.
External Identifier
If the identifier is used in the external linkage, then it is known as an external identifier. The
external identifiers can be function names, global variables.
It must be written in a lowercase letter. It can be written in both lowercase and uppercase letters.
Its meaning is pre-defined in the c compiler. Its meaning is not defined in the c compiler.
It does not contain the underscore character. It can contain the underscore character.
1. int main()
2. {
3. int a=10;
4. int A=20;
5. printf("Value of a is : %d",a);
6. printf("\nValue of A is :%d",A);
7. return 0;
8. }
Output
Value of a is : 10
Value of A is :20
The above output shows that the values of both the variables, 'a' and 'A' are different. Therefore, we
conclude that the identifiers are case sensitive.