C First Semester Notes-1
C First Semester Notes-1
C First Semester Notes-1
Introduction To C
The C Character Set
A character set in C Programming Language is set all valid characters that can be used to form words, numbers
and expression’s in source programs. The source character set is consist of the characters used for the source
program text, while the execution character set is the set of characters used during the execution of the
program. It is not necessary that source character set match and execution character set are same.
Uppercase A-Z
1. Letters
Lowercase a-z
Identifiers
An identifier is used for any variable, function, data definition, labels in your program etc.
Before starting any language, you must at least know how you name an identifier.
In C language, an identifier is a combination of alphanumeric characters, i.e. first begin with a
letter of the alphabet or an underline, and the remaining are letter of an alphabet, any numeric digit,
or the underline.
int student;
float marks;
Keywords
Keywords are predefined, reserved words in C language and each of which is associated with
specific features. These words help us to use the functionality of C language. They have special
meaning to the compilers.
There are total 32 keywords in C.
do if static while
Example
#include <stdio.h>
int main() {
char c = 'H';
int b = 6, c;
float _d = 7.6;
if(b<5)
else
return 0;
}
Output
Float value : 7.600000
Data Types
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.
3
The type void
The type specifier void indicates that no
value is available.
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 −
-32,768 to 32,767 or -
int 2 or 4 bytes 2,147,483,648 to
2,147,483,647
unsigned 8 bytes 0 to
long 18446744073709551615
To get the exact size of a type or a variable on a particular platform, you can use
the sizeof operator. The expressions sizeof(type) yields the storage size of the object or type in
bytes. Given below is an example to get the size of various type on a machine using different
constant defined in limits.h header file −
Live Demo
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <float.h>
return 0;
}
When you compile and execute the above program, it produces the following result on Linux −
CHAR_BIT : 8
CHAR_MAX : 127
CHAR_MIN : -128
INT_MAX : 2147483647
INT_MIN : -2147483648
LONG_MAX : 9223372036854775807
LONG_MIN : -9223372036854775808
SCHAR_MAX : 127
SCHAR_MIN : -128
SHRT_MAX : 32767
SHRT_MIN : -32768
UCHAR_MAX : 255
UINT_MAX : 4294967295
ULONG_MAX : 18446744073709551615
USHRT_MAX : 65535
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 space taken by a float type and its range values −
Live Demo
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <float.h>
return 0;
}
When you compile and execute the above program, it produces the following result on Linux −
Storage size for float : 4
FLT_MAX : 3.40282e+38
FLT_MIN : 1.17549e-38
-FLT_MAX : -3.40282e+38
-FLT_MIN : -1.17549e-38
DBL_MAX : 1.79769e+308
DBL_MIN : 2.22507e-308
-DBL_MAX : -1.79769e+308
Precision value: 6
The void Type
The void type specifies that no value is available. It is used in three kinds of situations −
1
Function returns as void
There are various functions in C which
do not return any value or you can say
they return void. A function with no
return value has the return type as void.
For example, void exit (int status);
2
Function arguments as void
There are various functions in C which
do not accept any parameter. A function
with no parameter can accept a void. For
example, int rand(void);
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.
Constants
Constants refer to fixed values that the program may not alter during its execution. These fixed
values are also called literals.
Constants can be of any of the basic data types like an integer constant, a floating constant, a
character constant, or a string literal. There are enumeration constants as well.
Constants are treated just like regular variables except that their values cannot be modified after
their definition.
Integer Literals
An integer literal can be a decimal, octal, or hexadecimal constant. A prefix specifies the base or
radix: 0x or 0X for hexadecimal, 0 for octal, and nothing for decimal.
An integer literal can also have a suffix that is a combination of U and L, for unsigned and long,
respectively. The suffix can be uppercase or lowercase and can be in any order.
Here are some examples of integer literals −
212 /* Legal */
215u /* Legal */
0xFeeL /* Legal */
078 /* Illegal: 8 is not an octal digit */
032UU /* Illegal: cannot repeat a suffix */
Following are other examples of various types of integer literals −
85 /* decimal */
0213 /* octal */
0x4b /* hexadecimal */
30 /* int */
30u /* unsigned int */
30l /* long */
30ul /* unsigned long */
Floating-point Literals
A floating-point literal has an integer part, a decimal point, a fractional part, and an exponent part.
You can represent floating point literals either in decimal form or exponential form.
While representing decimal form, you must include the decimal point, the exponent, or both; and
while representing exponential form, you must include the integer part, the fractional part, or
both. The signed exponent is introduced by e or E.
Here are some examples of floating-point literals −
3.14159 /* Legal */
314159E-5L /* Legal */
510E /* Illegal: incomplete exponent */
210f /* Illegal: no decimal or exponent */
.e55 /* Illegal: missing integer or fraction */
Character Constants
Character literals are enclosed in single quotes, e.g., 'x' can be stored in a simple variable
of char type.
A character literal can be a plain character (e.g., 'x'), an escape sequence (e.g., '\t'), or a universal
character (e.g., '\u02C0').
There are certain characters in C that represent special meaning when preceded by a backslash
for example, newline (\n) or tab (\t).
• Here, you have a list of such escape sequence codes −
•
#include <stdio.h>
int main() {
printf("Hello\tWorld\n\n");
return 0;
}
When the above code is compiled and executed, it produces the following result −
Hello World
String Literals
String literals or constants are enclosed in double quotes "". A string contains characters that are
similar to character literals: plain characters, escape sequences, and universal characters.
You can break a long line into multiple lines using string literals and separating them using white
spaces.
Here are some examples of string literals. All the three forms are identical strings.
"hello, dear"
"hello, \
dear"
#include <stdio.h>
#define LENGTH 10
#define WIDTH 5
#define NEWLINE '\n'
int main() {
int area;
return 0;
}
When the above code is compiled and executed, it produces the following result −
value of area : 50
The const Keyword
You can use const prefix to declare constants with a specific type as follows −
const type variable = value;
The following example explains it in detail −
Live Demo
#include <stdio.h>
int main() {
const int LENGTH = 10;
const int WIDTH = 5;
const char NEWLINE = '\n';
int area;
return 0;
}
When the above code is compiled and executed, it produces the following result −
value of area : 50
Note that it is a good programming practice to define constants in CAPITALS.
Variables
A variable is nothing but a name given to a storage area that our programs can manipulate. Each
variable in C has a specific type, which determines the size and layout of the variable's memory;
the range of values that can be stored within that memory; and the set of operations that can be
applied to the variable.
The name of a variable can be composed of letters, digits, and the underscore character. It must
begin with either a letter or an underscore. Upper and lowercase letters are distinct because C is
case-sensitive. Based on the basic types explained in the previous chapter, there will be the
following basic variable types −
1
char
Typically a single octet(one byte). It is
an integer type.
2
int
The most natural size of integer for the
machine.
3
float
A single-precision floating point value.
4
double
A double-precision floating point value.
5
void
Represents the absence of type.
C programming language also allows to define various other types of variables, which we will
cover in subsequent chapters like Enumeration, Pointer, Array, Structure, Union, etc. For this
chapter, let us study only basic variable types.
Variable Definition in C
A variable definition tells the compiler where and how much storage to create for the variable. A
variable definition specifies a data type and contains a list of one or more variables of that type
as follows −
type variable_list;
Here, type must be a valid C data type including char, w_char, int, float, double, bool, or any
user-defined object; and variable_list may consist of one or more identifier names separated by
commas. Some valid declarations are shown here −
int i, j, k;
char c, ch;
float f, salary;
double d;
The line int i, j, k; declares and defines the variables i, j, and k; which instruct the compiler to
create variables named i, j and k of type int.
Variables can be initialized (assigned an initial value) in their declaration. The initializer consists
of an equal sign followed by a constant expression as follows −
type variable_name = value;
Some examples are −
extern int d = 3, f = 5; // declaration of d and f.
int d = 3, f = 5; // definition and initializing d and f.
byte z = 22; // definition and initializes z.
char x = 'x'; // the variable x has the value 'x'.
For definition without an initializer: variables with static storage duration are implicitly initialized
with NULL (all bytes have the value 0); the initial value of all other variables are undefined.
Variable Declaration in C
A variable declaration provides assurance to the compiler that there exists a variable with the
given type and name so that the compiler can proceed for further compilation without requiring
the complete detail about the variable. A variable definition has its meaning at the time of
compilation only, the compiler needs actual variable definition at the time of linking the program.
A variable declaration is useful when you are using multiple files and you define your variable in
one of the files which will be available at the time of linking of the program. You will use the
keyword extern to declare a variable at any place. Though you can declare a variable multiple
times in your C program, it can be defined only once in a file, a function, or a block of code.
Example
Try the following example, where variables have been declared at the top, but they have been
defined and initialized inside the main function −
Live Demo
#include <stdio.h>
// Variable declaration:
extern int a, b;
extern int c;
extern float f;
int main () {
/* variable definition: */
int a, b;
int c;
float f;
/* actual initialization */
a = 10;
b = 20;
c = a + b;
printf("value of c : %d \n", c);
f = 70.0/3.0;
printf("value of f : %f \n", f);
return 0;
}
When the above code is compiled and executed, it produces the following result −
value of c : 30
value of f : 23.333334
The same concept applies on function declaration where you provide a function name at the time
of its declaration and its actual definition can be given anywhere else. For example −
// function declaration
int func();
int main() {
// function call
int i = func();
}
// function definition
int func() {
return 0;
}
Lvalues and Rvalues in C
There are two kinds of expressions in C −
• lvalue − Expressions that refer to a memory location are called "lvalue" expressions. An
lvalue may appear as either the left-hand or right-hand side of an assignment.
• rvalue − The term rvalue refers to a data value that is stored at some address in memory.
An rvalue is an expression that cannot have a value assigned to it which means an rvalue
may appear on the right-hand side but not on the left-hand side of an assignment.
Variables are lvalues and so they may appear on the left-hand side of an assignment. Numeric
literals are rvalues and so they may not be assigned and cannot appear on the left-hand side. Take
a look at the following valid and invalid statements −
int g = 20; // valid statement
Declarations
In C programming, variables which are to be used later in different parts of the
functions have to be declared. Variable declaration tells the compiler two things:
•
The name of the variable
• The type of data the variable will hold
There are two ways of declaring variable in C programming.
data_type var1,var2,...varn;
Variables can also be defined in multiple lines instead of on the same line.
data_type var1;
data_type var2;
data_type varn;
When the variables are declared in single line, then the variables must be separated by
commas.
For example:
int age;
float weight;
char gender;
In these examples, age, weight and gender are variables which are declared as integer
data type, floating data type and character data type respectively.
Here, type is an existing data type and identifier is the “new name” given to the data
type. Here, the new type is ‘new’ only in name but not the data type.
Consider an example:
Here, age represents int and weight represent float which can be used later in the
program to declare variables as follows:
age boy1,boy2;
weight b1,b2;
Here, boy1 and boy2 are declared as as integer data type and b1 & b2 are declared as
floating integer data type.
The main advantage of using user-defined type declaration is that we can create
meaningful data type names for increasing the readability of a program.
Another user-defined data type is enumerated data type. The general syntax of
enumerated data type is:
Here, identifier is a user-defined enumerated data type which can be used to declare
variables that can have one of the values enclosed within the braces. The values inside
the braces are known as enumeration constants. After this declaration, we can declare
variables to be of this ‘new’ type as:
The enumerated variables v1, v2, … vn can only have one of the values value1,
value2, … valuen. The following kinds of declarations are valid:
v1=value5;
v3=value1;
day_st = January;
day_end = December;
if (day_st == February)
day_end = November;
The compiler automatically assigns integer digits begriming with 0 to all the
enumeration constants. That is, the enumeration constant value1 is assigned
0, value2 is assigned 1, and so on. However, the automatic assignments can be
overridden by assigning values explicitly to thee enumeration constants.
For example:
Here, the constant January is assigned value 1. The remaining values are assigned
values that increase successively by 1.
Expressions
Example
Given below is the C program explaining the different types of expressions in C language −
Live Demo
#include<stdio.h>
int main(){
int a,b,c,d,z;
int p,q,r,s,t,u,v;
scanf("%d%d%d%d",&a,&b,&c,&d);
r=a++;
s=--b;
t=a+b;
u=c-d;
v=a+(5*b);
z = (5>3) ? 1:0;
Output
You will see the following output −
Statements
C programs are collection of Statements, statements is an executable part of the program it will do
some action. In general all arithmetic actions and logical actions are falls under Statements Categories
anyway there are few Statement categories
▪ Expression Statements.
▪ Compound Statements.
▪ Selection Statements.
▪ Iterative Statements.
▪ Jump Statements.
Expression Statements:
It is combination of variables,Constants,operators,Function Calls and followed by a
semicolon. Expression can be any operation like Arithmetic operation or Logical Operation.
Few Examples for expression Statements
X = Y + 10 ;
20 > 90;
a?b:c;
a = 10 + 20 * 30;
; (This is NULL Statement ).
Compound Statement :
Compound statement is combination of several expression statements. Compound Statement
is Enclosed within the Braces { }.
Compound statement is also called as Block Statement.
{
int a=10,b=20,c;
c = a + b;
printf(“value of C is : %d n”,c);
}
▪ for loop.
▪ while loop.
▪ do-while loop.
Jump Statements :
These are Unconditional statements Jump statements are useful for Transfer the Control
one part of program to other part of Program there are few Jump Statements in C
▪ goto.
▪ continue.
▪ break.
▪ return.
All these Selection and Iterative and Jump Statements are Keywords and all are Lower
Case Characters.
Data Input and Output
Single Character Input
getchar() is used to get or read the input (i.e a single character) at run time.
Declaration:
int getchar(void);
Example Declaration:
char ch;
ch = getchar();
Return Value:
This function return the character read from the keyboard.
Example Program:
/* Example Program For Single Character Input Function : getchar() In C Programming Language
little drops @ thiyagaraaj.com
Coded By:THIYAGARAAJ MP */
// Header Files
#include<stdio.h>
#include<conio.h>
//Main Function
void main()
{
char ch;
ch = getchar();
printf("Input Char Is :%c",ch);
}
Declaration:
int putch(variable_name);
char ch = 'a';
putchar(ch);
Remarks:
// Header Files
#include<stdio.h>
#include<conio.h>
//Main Function
void main()
{
char ch='a';
putchar(ch);
getch();
}
Sample Output
Scanf
The C library function int scanf(const char *format, ...) reads formatted input from stdin.
Declaration
Following is the declaration for scanf() function.
int scanf(const char *format, ...)
Parameters
• format − This is the C string that contains one or more of the following items −
Whitespace character, Non-whitespace character and Format specifiers. A format
specifier will be like [=%[*][width][modifiers]type=] as explained below −
1
*
This is an optional starting asterisk
indicates that the data is to be read from
the stream but ignored, i.e. it is not
stored in the corresponding argument.
2
width
This specifies the maximum number of
characters to be read in the current
reading operation.
3
modifiers
Specifies a size different from int (in the
case of d, i and n), unsigned int (in the
case of o, u and x) or float (in the case
of e, f and g) for the data pointed by the
corresponding additional argument: h :
short int (for d, i and n), or unsigned
short int (for o, u and x) l : long int (for
d, i and n), or unsigned long int (for o, u
and x), or double (for e, f and g) L : long
double (for e, f and g)
4
type
A character specifying the type of data
to be read and how it is expected to be
read. See next table.
• additional arguments − Depending on the format string, the function may expect a
sequence of additional arguments, each containing one value to be inserted instead of each
%-tag specified in the format parameter, if any. There should be the same number of these
arguments as the number of %-tags that expect a value.
Return Value
On success, the function returns the number of items of the argument list successfully read. If a
reading error happens or the end-of-file is reached while reading, the proper indicator is set (feof
or ferror) and, if either happens before any data could be successfully read, EOF is returned.
Example
The following example shows the usage of scanf() function.
#include <stdio.h>
int main () {
char str1[20], str2[30];
return(0);
}
Printf
The C library function int printf(const char *format, ...) sends formatted output to stdout.
Declaration
Following is the declaration for printf() function.
int printf(const char *format, ...)
Parameters
• format − This is the string that contains the text to be written to stdout. It can optionally
contain embedded format tags that are replaced by the values specified in subsequent
additional arguments and formatted as requested. Format tags prototype
is %[flags][width][.precision][length]specifier, which is explained below −
1
c
Character
2
d or i
Signed decimal integer
3
e
Scientific notation (mantissa/exponent)
using e character
4
E
Scientific notation (mantissa/exponent)
using E character
5
f
Decimal floating point
6
g
Uses the shorter of %e or %f
7
G
Uses the shorter of %E or %f
8
o
Signed octal
9
s
String of characters
10
u
Unsigned decimal integer
11
x
Unsigned hexadecimal integer
12
X
Unsigned hexadecimal integer (capital
letters)
13
p
Pointer address
14
n
Nothing printed
15
%
Character
1
-
Left-justify within the given field width;
Right justification is the default (see
width sub-specifier).
2
+
Forces to precede the result with a plus
or minus sign (+ or -) even for positive
numbers. By default, only negative
numbers are preceded with a -ve sign.
3
(space)
If no sign is going to be written, a blank
space is inserted before the value.
4
#
Used with o, x or X specifiers the value
is preceded with 0, 0x or 0X
respectively for values different than
zero. Used with e, E and f, it forces the
written output to contain a decimal point
even if no digits would follow. By
default, if no digits follow, no decimal
point is written. Used with g or G the
result is the same as with e or E but
trailing zeros are not removed.
5
0
Left-pads the number with zeroes (0)
instead of spaces, where padding is
specified (see width sub-specifier).
1
(number)
Minimum number of characters to be
printed. If the value to be printed is
shorter than this number, the result is
padded with blank spaces. The value is
not truncated even if the result is larger.
2
*
The width is not specified in the format
string, but as an additional integer value
argument preceding the argument that
has to be formatted.
1
.number
For integer specifiers (d, i, o, u, x, X) −
precision specifies the minimum
number of digits to be written. If the
value to be written is shorter than this
number, the result is padded with
leading zeros. The value is not truncated
even if the result is longer. A precision
of 0 means that no character is written
for the value 0. For e, E and f specifiers
− this is the number of digits to be
printed after the decimal point. For g
and G specifiers − This is the maximum
number of significant digits to be
printed. For s − this is the maximum
number of characters to be printed. By
default all characters are printed until
the ending null character is encountered.
For c type − it has no effect. When no
precision is specified, the default is 1. If
the period is specified without an
explicit value for precision, 0 is
assumed.
2
.*
The precision is not specified in the
format string, but as an additional
integer value argument preceding the
argument that has to be formatted.
Sr.No. Length & Description
1
h
The argument is interpreted as a short
int or unsigned short int (only applies to
integer specifiers: i, d, o, u, x and X).
2
l
The argument is interpreted as a long int
or unsigned long int for integer
specifiers (i, d, o, u, x and X), and as a
wide character or wide character string
for specifiers c and s.
3
L
The argument is interpreted as a long
double (only applies to floating point
specifiers: e, E, f, g and G).
• additional arguments − Depending on the format string, the function may expect a
sequence of additional arguments, each containing one value to be inserted instead of each
%-tag specified in the format parameter (if any). There should be the same number of
these arguments as the number of %-tags that expect a value.
Return Value
If successful, the total number of characters written is returned. On failure, a negative number is
returned.
Example
The following example shows the usage of printf() function.
Live Demo
#include <stdio.h>
int main () {
int ch;
Else if ladder:-
This is a type of nesting in which there is an if-else statement in every else
part except the last else part. This type of nesting is called else if ladder.
The general syntax and flow chart of else if ladder is as follows:-
If(condition1)
statementA;
else if(condition2)
statementB;
else if(condition3)
statementC;
else
statementD;
A program to illustrate the else if ladder:-
/*program to find the grade of the student*/
#include<stdio.h>
#include<conio.h>
void main()
{
int marks;
printf(“enter the percentage of the student”);
scanf(“%d”,&marks);
if(marks>=80)
printf(“your grade is a”);
else if(marks>=70)
printf(“your grade is b”);
else if(marks>=60)
printf(“your grade is c”);
else if(marks>=50)
printf(“your grade is d”);
else
printf(“you are fail”);
getch();
}
SWITCH STATEMENT
Switch case statements are a substitute for long if statements and has
more
flexibility and a clearer format than else-if ladder. This statement is used
to select one out of the several numbers of alternatives present in a block.
This selection statement successively tests the value of an expression
against a list of integer or character constants. When a match is found, the
statements associated with that constant are executed.
The general syntax of switch case statement is as follows:-
switch(expression)
{
case constant1: statements;
case constant2: statements;
case constant3: statements;
………………………
………………………
case constantN: statements;
default : statement;
}
Here switch, case and default are keywords.
The expression following the switch keyword must give an integer value.
This expression can be any integer or character variable, or a function call
that returns an integer. It can also be arithmetic, relational, logical or
bitwise expression yielding an integer. It can be integer or character
constant also. Data types long int and short int are also allowed.The
constant following the case keyword should be of integer or character
type. We cannot use floating point or string constant.
A program to explain switch case statement
/*program to print day of the week*/
#include<stdio.h>
#include<conio.h>
void main()
{
int day;
clrscr();
printf(“enter the day number from 1 to7”);
scanf(“%d”,&day);
switch(day)
{
case 1: printf(“monday”);
break;
case 2:printf(“tuesday”);
break;
case 3: printf(“wednesday”);
break;
case 4:printf(“thursday”);
break;
case 5: printf(“friday”);
break;
case 6:printf(“saturday”);
break;
case 7: printf(“sunday”);
break;
default:printf(“wrong input”);
}
getch();
}
NOTE:- In switch case statement, if we do not associate a break statement
with every case then from the case for which the expression matches with
the constant, all the statements are executed until the switch case block
ends. This situation is referred to as Fall Through. Conditional operator:-
It is a ternary operator and is used to perform simple conditional
operations. It is used to do operations similar to if-else statement.
The general syntax of conditional operator is as under:-
Test expression? expression1:expression2
Here firstly the test expression is evaluated.
If the test expression evaluates to true then the expression1 is evaluated
and it becomes the value of the whole expression.
If the test expression evaluates to false then the expression2 is evaluated
and it becomes the value of the whole expression.
For eg., a>b ? a : b
Here firstly the expression a>b is evaluated. If it evaluates to true then the
value of a becomes the value of the whole expression otherwise value of
b becomes the value of whole expression.
BREAK STATEMENT
Syntax
The syntax for a break statement in C is as follows −
break;
Flow Diagram
Example
Live Demo
#include <stdio.h>
int main () {
return 0;
}
When the above code is compiled and executed, it produces the following result −
value of a: 10
value of a: 11
value of a: 12
value of a: 13
value of a: 14
value of a: 15
CONTINUE STATEMENT
Continue is also a loop control statement just like the break
statement. continue statement is opposite to that of break statement, instead of
terminating the loop, it forces to execute the next iteration of the loop.
As the name suggest the continue statement forces the loop to continue or
execute the next iteration. When the continue statement is executed in the loop,
the code inside the loop following the continue statement will be skipped and
next iteration of the loop will begin.
Syntax:
continue;
Example:
Consider the situation when you need to write a program which prints number
from 1 to 10 and but not 6. It is specified that you have to do this using loop
and only one loop is allowed to use.
Here comes the usage of continue statement. What we can do here is we can
run a loop from 1 to 10 and every time we have to compare the value of iterator
with 6. If it is equal to 6 we will use the continue statement to continue to next
iteration without printing anything otherwise we will print the value.
Below is the implementation of the above idea:
#include <stdio.h>
nt main() {
// loop from 1 to 10
// If i is equals to 6,
// without printing
if (i == 6)
continue;
else
return 0;
Output:
1 2 3 4 5 7 8 9 10
LOOPING STATEMENT
do-while loop :-
The do-while statement is also used for looping. It is similar to while loop
and is used for the problems where it is not known in advance that how
many times the statement or block of statements will be executed.
However, unlike while loop, in case of do-while, firstly the statements
inside the loop body are executed and then the condition is evaluated. As
a result of which this loop is executed at least once even if the condition
is initially false. After that the loop is repeated until the condition
evaluates to false.
Since in this loop the condition is tested after the execution of the loop, it
is also known as posttest loop.
The general syntax of do-while loop is as follows:-
do
{
Statement(s);
}while(condition);
The flow chart of do-while is given as under:-
For loop :-
The general syntax of for loop consists of three expressions separated by
semicolons. It is given as follows:-
for(expression1;expression2;expression3)
Body of loop
condition
Next statement
out of loop
{
Statement(s);
}
Here the expression1 is the initialization expression,expression2 is the test
expression and expression3 is the update expression. Expression1 is
executed only once when the loop starts and is used to initialize the loop
variables. Expression2 is a condition and is tested before each iteration of
the loop. Expression3 is an update expression and is executed each time
after the body of the loop is executed.
The flow chart of for loop is given as follows:-
FUNCTIONS:
• Defining A Function, Accessing A Function, Function Prototypes,
• Passing Arguments to a Function, Return Values and Their Types,
Category of Functions, Recursion,
• Storage Classes: Automatic Variables, External, Variables, Static
Variables, Register Variable
➢ C functions
One of the strength of the c language is c functions. C enable s it’s programmers to break up a program into
segments commonly known as functions. Every function in the program is supposed to perform a well
defined task
C functions can be classified into two categories, namely library functions and user defined functions.
1. Library functions
2. User-defined functions
Library functions are those functions which are already defined in C library. These functions are not
required to be written by us. Example printf() , scanf() , strcat() etc. You just need to include appropriate
header files to use these functions.
User-defined functions on the other hand, are those functions which are defined by the user at the time of
writing program. main() is an example of user-defined functions. main() is a function called by the
Operating system when program is loaded and returns to the Operating system when terminated.
This is very similar to the function header line except the terminating semicolon.
Points to note:
1. The parameter list must be separated by commas.
2. The parameter names do not need to be the same in the prototype declaration and the function
definition.
3. The types must match the types of parameters in the function definition, in number and order
4. Use of parameter names in the declaration is optional
5. If the function has no formal parameters, the list is written as (void).
6. The return type is optional, when the function returns int type data.
7. The return type must be void if no value is returned.
8. When the declared types do not match with the types in the function definition, compiler will
Produce an error.
When a function does not take any parameters and does not return any value, its prototype is
written as:
void display (void):
A prototype declaration may be placed in two places in a program
When we place the declaration above all the functions (in the global declaration section), the prototype
is referred to as a global prototype. Such declarations are available for all the functions in the program.
When we place it in a function definition (In the local declaration section), the prototype is called a
local prototype. Such declarations are primarily used by the functions containing them. The place of
declaration of a function defines a region in a program in which the function may be used by other
functions. This region is known as the scope of the function. It is a good programming style to declare
prototypes in the global declaration section before main. It adds flexibility, provides an excellent quick
reference to the functions used in the program, and enhances documentation
➢ Function definition :
It is an independent program module that is specially written to implement the requirements of
Function. It includes the following elements.
a) Function type
b) Function name Function header
c) List of parameters
d) Local variable declarations
e) Function statements Function body
f) return statements
The general format of function definition to implement these ywo parts is given below
Function header consist of three parts: the function type (also known as return type),the function name
and the formal parameter list. Not that the semicolon is not used at the end of the function header.
Function type: it specifies the type of value (like float or double) that the function is expected to return
to the program calling the function. If the return type is not explicitly specified C will assume that it is an
integer type. If the function is not returning anything, then we need to specify the return type as void.
Function name: it is any valid c identifier and therefore must follow the same rules of formation as other
variable names in C. the name should be appropriate to the task performed by the function.
List of parameters: also known as arguments. It declares the variables that will receive the data sent by
the calling program. They serve as the input data to the function to carry out the specified task. Since they
represent the actual input values they are often referred to as formal parameters.
Function body contains the declarations and statements necessary for performing the required task .The
body enclosed in braces, contains three parts in the given order
1) Local declarations that specify the variables needed by the function
2) Function statements that perform the task of the function
3) A return statement that returns the value evaluated by the function.
If a function returns nothing, return statement can be avoided. However, note that its return type should be
specified as void. It is nice to have a return statement even for void functions. A function can return only a
single value
Example
Note
1. When a function reaches its return statement, the control is transferred back to the calling program
. In the absence of a return statement, the closing brace acts as a void return.
2. A local variable is a variable that is defined inside a function and used without having any role in
the communication between functions.
➢ Function call:
Functions call statement access the function, which means program control passes to that function. After
completion of the function the program control returns back to the calling environment
• The general form of function call is
function_name(<variable 1,variabke 2,…….>); function_name() ;
OR OR
variable_name=function_name(variable1,variabke2,…….>); variable_name = function_name();
A function can be called by simply using the function name followed by a list of parameters(or arguments), if any
enclosed in paranthesis.example.
main()
{
Int y;
y=mul(10,5); /* function call */
Printf(“%d\n”,y);
}
When the compiler encounters a function call, the control is transferred to the function mul(). This
function is then executed line by line as described and a value is returned when a return statement is
encountered. This value is assigned to y. This is illustrated below:
main()
{
int y:
y =mul (10,5); /*call*/
}
int mul (int x, int y)
{
int p; /* local variable*/
p=x *y; /*x =10, y = 5*/
return (p);
}
The function call sends two integer values 10 and 6 to the function
Which are assigned to x and y respectively. The function computes the product x and y, assigns the
result to the local variable p, and then returns the value 25 to the main where it is assigned to y again
There are many different ways to call a function. Listed below are some of the ways the function mul
can be invoked
mul (10,5)
mul (m. 5)
mul (10. n)
mul (m, n)
mul (m + 5. 10)
mul (10, mul(m,n))
mul (expression, expression2)
Note that the sixth call uses its own call as its one of the parameters, When we use expressions, they
should be evaluated to single values that can be passed as actual parameters, A function which returns a
value can be used in expressions like any other variable. Each of the following statements is valid:
mul(a,b) =15;
is invalid
A function that does not return any value may not be used in expressions; but can be called in
to perform certain tasks specified in the function.. Such functions may be called in by simply stating their
names as independent statements
Example:
main()
{
printline();
}
Parameters Everywhere!
Parameters (also known as arguments) are used in following three places:
1. in declaration (prototypes),
2. in function call, and
3. in function definition.
• The parameters used in prototypes and function definitions are called formal parameters.
• The parameters used in function calls are called actual parameters.
• Actual parameters used in a calling statement may be simple constants, variables, or expressions.
• The formal and actual parameters must match exactly in type, order and number. Their names,
however, do not need to match.
➢ Passing Arguments To A Function:
There are two approaches to passing argument to a function:
• Call by Value
• Call by Reference/Address
Call by Value
In this approach, the values are passed as function argument to the definition of function.
o In call by value method, the value of the actual parameters is copied into the formal parameters.
In other words, we can say that the value of the variable is used in the function call in the call
by value method.
o In call by value method, we can not modify the value of the actual parameter by the formal
parameter.
o In call by value, different memory is allocated for actual and formal parameters since the value
of the actual parameter is copied into the formal parameter.
o The actual parameter is the argument which is used in the function call whereas formal
parameter is the argument which is used in the function definition.
void main()
{
int A=10,B=20;
fun(A,B); //Statement 1
}
void fun(int X,int Y) //Statement 2
{
X=11;
Y=22;
}
Output :
In the above example, statement 1 is passing the values of A and B to the calling function fun(). fun() will
receive the value of A and B and put it into X and Y respectively. X and Y are value type variables and
are local to fun(). Any changes made by value type variables X and Y will not effect the values of A and
B.
Call by reference
In this approach, the references/addresses are passed as function argument to the definition of function
o In call by reference, the address of the variable is passed into the function call as the actual
parameter.
o The value of the actual parameters can be modified by changing the formal parameters since the
address of the actual parameters is passed.
o In call by reference, the memory allocation is similar for both formal parameters and actual
parameters. All the operations in the function are performed on the value stored at the address
of the actual parameters, and the modified value gets stored at the same address.
#include<stdio.h>
void main()
{
int A=10,B=20;
printf("\nValues before calling %d, %d",A,B);
fun(&A,&B); //Statement 1
printf("\nValues after calling %d, %d",A,B);
}
void fun(int *X,int *Y) //Statement 2
{
*X=11;
*Y=22;
}
Output :
Values before calling 10, 20
Values after calling 11, 22
In the above example, statement 1 is passing the reference of A and B to the calling function fun(). fun()
must have pointer formal arguments to receive the reference of A and B. In statement 2 *X and *Y is
receiving the reference A and B. *X and *Y are reference type variables and are local to fun(). Any
changes made by reference type variables *X and *Y will change the values of A and B respectively
➢ Return Values And Their Types:
A function may or may not send back any value to the calling function. In it does it is done through
the return statement. While it is possible to pass to the called function any number of
values, the called function can only return one value per call, at the most The return statement can
take one of the following forms:
return;
or
return(expression)
The first, the 'plain' return does not return any value it acts much as the closing brace of the function.
When a return is encountered the controlisimmediately passed back to the calling function. An example of
the use of a simple return is as follows:
1f(error)
return;
The second form of roturn with an expression returns the value of the expression. For example, the
function
int mul (int x, int y)
int p:
px"y
return(p):
returns the value of p which is the product of the values of x and y. The last two statements can be
combined into one statement as follows:
return (x*y);
A function may have more than one return statements. This situation arises when the value returned is
based on certain conditions. For example:
if( x < 0)
return(0);
else
return (1):
What type of data does a function return? All functions by default return int type data. But what
happens if a function must return some other type? We can force a function to return a particular type of
data by using a type specifier in the function header as discussed earlier. When a value is returned, it is
automatically cast to the function's type. In functions that do computations using doubles, yet return ints,
the returned value will be truncated to an integer. For instance, the function
will return the value 7. only the integer part of the result.
NESTING OF FUNCTIONS
C permits nesting of functions freely. main can call function1, which calls function2, which calls
function3, ...... and so on. There is in principle no limit as to how deeply functions can be nested.
Consider the following program:
}
The above program calculates the ratio a/b-c and prints the result. We have the following three
functions:
main()
ratio()
difference()
main reads the values of a, b, and cand calls the function ratio to calculate the value alb-c). This ratio
cannot be evaluated if (6-c) = 0. Therefore, ratio calls another function difference to test whether the
difference (b-c) is zero or not difference returns 1. if b is not equal to c; otherwise returns zero to the
function ratio. In tum, ratio calculates the value a/b-c) if it receives 1 and returns the result in float. In
tase, ratio receives zero from difference, it sends back 0.0 to main indicating that (b-C) = 0 Nesting of
function calls is also possible. For example, a statement like
P = mul(mul(5,2).6);
Is valid. This represents two sequential function calls. The inner function call is evaluated first and the
ratured value is again used as an actual argument in the outer function call. If mul returns the product
of its arguments, then the value of p would be 60 (= 5 x 26).Note that the nesting does not mean defining
one function within another. Doing this is illegal.
➢ Category Of Functions
There can be 4 different types of user-defined functions they are:
1. Function with no arguments and no return value
2. Function with no arguments and a return value
3. Function with arguments and no return value
4. Function with arguments and a return value
1. Function with no arguments and no return value
When a function has no arguments it does not receive any data from the calling function. Similarly when it
does not return a value the calling function does not receive any data from the called function. Such
functions can either be used to display information or they are completely dependent on user inputs.
Function declaration : void function();
Function call : function();
Function definition : void function()
{
statements;
}
Example:
#include<stdio.h>
main (){
void sum ();
clrscr ();
sum ();
getch ();
}
void sum (){
int a,b,c;
printf("enter 2 numbers:\n");
scanf ("%d%d", &a, &b);
c = a+b;
printf("sum = %d",c);
}
Output
Enter 2 numbers:
3
5 sum=
2.Function with no arguments and a return value
There could be occasions where we may need to design functions that may not take any arguments but
returns a value to the calling function. A example for this is getchar function it has no parameters but it
returns an integer an integer type data that represents a character.
Example:
#include<stdio.h>
main (){
int sum ();
int c;
c= sum ();
printf(“sum = %d”,c);
getch ();
}
int sum (){
int a,b,c;
printf(“enter 2 numbers”);
scanf (“%d%d”, &a, &b);
c = a+b;
return c;
}
Output
Enter two numbers 10 20
30
3.Function with arguments and no return value
When a function has arguments, it receive any data from the calling function but it returns no values.
Example:
#include<stdio.h>
main (){
void sum (int, int );
int a,b;
printf("enter 2 numbers");
scanf("%d%d", &a,&b);
sum (a,b);
getch ();
}
void sum ( int a, int b){
int c;
c= a+b;
printf (“sum=%d”, c);
}
Output
Enter two numbers 10 20
Sum=30
4.Function with arguments and a return value
Example:
#include<stdio.h>
main (){
int sum ( int,int);
int a,b,c;
printf("enter 2 numbers");
scanf("%d%d", &a,&b);
c= sum (a,b);
printf ("sum=%d", c);
getch ();
}
int sum ( int a, int b ){
int c;
c= a+b;
return c;
Output
Enter two numbers 10 20
Sum=30
➢ Recursion:
When a called function in turn calls another function process of chaining occurs. Recursion is a special
case of this process, where a function calls itself. a very simple example of recursion is presented below.
main()
{
Printf(“This is an example of recursion”);
main();
}
When executed, this program will produce an output something like this:
This is an example of recursion
This is an example of recursion
This is an example of recursion
This is an ex
Execution is terminated abruptly, otherwise the execution will continue indefinitely.
• Recursive functions uses a stack of data areas (consists of parameters, local variables and certain system
information) called ‘runtime stack’
• The memory area for each call is placed on the top of stack and taken off when the execution of the call
is complete • C uses this stacking principle for all nested function calls including recursion
The factors of a given number n is expressed as a series of repetitive multiplications as shown below:
factorial of n = n(n-1)(n-2).........1.
For example
factorial of 4 = 4 x 3 x 2 x 1 = 24
A function to evaluate factorial of n is as follows:
factorial(int n)
{
int fact;
if (n=-1)
return(1);
else
fact - nefactorial(n-1);
return(fact);
}
Let us see how the recursion works. Assume n = 3. Since the value of n is not 1, the statement
fact - n * factorial(n-1);
will be executed with n = 3. That is,
fact - 3 * factorial(2);
will be evaluated. The expression on the right-hand side includes a call to factorial with n = 2. This call
will return the following value:
2.*factorial(1)
Once again factorial is called with n = 1. This time, the function returns 1. The sequence of operations can
be summarized as follows:
fact = 3 * factorial(2)
= 3.2. factorial(1)
= 3:21
=6
b) Fibonacci series using recursion (1,1,2,3,5,8,..)
• fib(n)= fib(n-1)+fib(n-2)
# include<stdio.h>
int fib(int);
int main()
{
int n,i;
printf(“Enter the number of terms”);
scanf(“%d”,&n);
for(i =1;i<=n,i++)
printf(“ %d ”, fib(i));
return 0;
}
/* function using recursion */
int fib(int n)
{
if (n==1) ||(n==2)
return 1;
else
return ( fib(n-1)) + fib(n-2) );
}
# include<stdio.h>
int sum (int);
int main()
{
int n,s;
printf(“Enter the number”);
scanf(“%d”,&n);
s= sum(n);
printf(“sum of digits of %d = %d”, n,s);
return 0;
}
/* function using recursion */
int sum(int n)
{
if (n==0)
return 0;
else
return ( n%10 +sum(n/10)) ;
Recursive functions can be effectively used to solve problems where solution is expressed in terms of
successively applying the same solution to subsets of the problem. When we write recursive functions we
must have an if statement somewhere to force the function to return without the recursive calls being
executed. Otherwise, the function will never return.
Scope: The region of the source code over which the declaration of an identifier is visible is
called the scope of the identifier. Scope relates to the accessibility, the period of existence and
the boundary of usage of variables in a statement block or a function
Extent: The period of time for which the memory is associated with the identifier is called
extent of the identifier
Global variables – variables that are declared outside all functions and that can be accessed by all
functions
• Created at the beginning of the program and remain in existence till the end of execution •If not initialized
, it takes the value zero by default
•If a global and local variable has the same name, in the function local variable is used and global variable
is ignored.
Local variables –variables declared within the function and is usable only inside the function • created
automatically at the point of their declaration and ends when control is transferred to the calling point
•If not initialized takes some unknown junk value.
➢ Storage Classes:
Storage Classes are used to describe the features of a variable/function. These features basically
include the scope, visibility and life-time which help us to trace the existence of a particular variable
during the runtime of a program. C provides four storage class specifiers to be used with data type
specifiers in the declaration statement.
The general form of variable declaration that includes storage class specifier is
• By default all variables within a function are automatic, i.e., these variables are created automatically
when the function is invoked.
• Even if variable declaration does not include the keyword auto, such variables are implicitly specified as
belonging to automatic storage class
• These variables are local to the function and has life so long as control is within the function.
•If not initialized, they take some garbage value
Syntax:
Example:
#include<stdio.h>
void display();
void main()
{
auto int a=10; //OR int a=10;
printf("\nA : %d",a);
display();
printf("\nA : %d",a);
}
void display()
{
int a=20; //OR auto int
a=20;
printf("\nA : %d",a);
}
Output :
A : 10
A : 20
A : 10
The static storage class instructs the compiler to keep a local variable in existence during the life-time of
the program instead of creating and destroying it each time it comes into and goes out of scope.
Therefore, making local variables static allows them to maintain their values between function calls.
The static modifier may also be applied to global variables. When this is done, it causes that variable's
scope to be restricted to the file in which it is declared.
In C programming, when static is used on a global variable, it causes only one copy of that member to be
shared by all the objects of its class.
• A static variable is allotted a permanent storage location in memory. Its default value is zero
• These are not destroyed on function’s exit, but has life for the entire program duration
• They are visible only within the function
• These variables will retain their previous values from the previous call to the succeeding call
Syatax:
static Data-type Variable-name;
Example:
#include<stdio.h>
void display();
void main()
{
display();
display();
display();
}
void display()
{
static int a=1;
printf("\nA : %d",a);
a++;
Output :
A:1
A:2
A:3
In the above example, we does not use static keyword then the output will be :
Output :
A:1
A:1
A:1
• These variables are stored in CPU registers and hence speeds up execution
• Register specifier can be applied only to int and char type
• The number of register storage class variables is limited by the number of registers. if more
variables are specified, those above the limit will be converted as automatic variables
• Scope, life time and initial value are same as automatic variables
• Cannot apply Address operator (&).
The register should only be used for variables that require quick access such as counters.
Syntax:
Example
#include <stdio.h>
int main()
{
register int i;
for( i=1; i<=20000; i++)
printf(“%d “, i);
return 0;
}
• External storage class (extern)
Extern stands for external storage class. Extern storage class is used when we have global functions or
variables which are shared between two or more files. Keyword extern is used to declaring a global variable
or function in another file to provide the reference of variable or function which have been already defined
in the original file.
The variables defined using an extern keyword are called as global variables. These variables are accessible
throughout the program. Notice that the extern variable cannot be initialized it has already been defined in
the original file
• These are global variables. If shared between functions within a single file no need to specify
extern. Initial value 0
•If several programs are to be written and compiled separately and later linked to form an executable
program, and some variables are to be used by all/some programs then we use external storage class.
Syntax:
OR
Data-type Variable-name;
dataType arrayName[arraySize];
For example,
float mark[5];
It's important to note that the size and type of an array cannot be changed once it is
declared.
Suppose you declared an array mark as above. The first element is mark[0], the
second element is mark[1] and so on.
Few keynotes:
Arrays have 0 as the first index, not 1.
If the size of an array is n, to access the last element, the n-1 index is used. In this
example, mark[4]
Suppose the starting address of mark[0] is 2120d. Then, the address of the mark[1]
will be 2124d. Similarly, the address of mark[2] will be 2128d and so on.
For example,
Here, we haven't specified the size. However, the compiler knows its size is 5 as
we are initializing it with 5 elements.
Example 1: Array Input/Output
// Program to take 5 values from the user and store them in an array
// Print the elements stored in the array
#include <stdio.h>
int main() {
int values[5];
printf("Enter 5 integers: ");
// taking input and storing it in an array
for(int i = 0; i < 5; ++i) {
scanf("%d", &values[i]);
}
printf("Displaying integers: ");
Using Arrays
Elements of an array are accessed by specifying the index ( offset ) of the desired
element within square [ ] brackets after the array name.
Array subscripts must be of integer type. ( int, long int, char, etc. )
VERY IMPORTANT: Array indices start at zero in C, and go to one less than the
size of the array. For example, a five element array will have indices zero through
four. This is because the index in C is actually an offset from the beginning of the
array. ( The first element is at the beginning of the array, and hence has zero
offset. )
The first sample program uses loops and arrays to calculate the first twenty
Fibonacci numbers. Fibonacci numbers are used to determine the sample points
used in certain optimization methods.
#include <stdlib.h>
#include <stdio.h>
int i, fibonacci[ 20 ];
fibonacci[ 0 ] = 0;
fibonacci[ 1 ] = 1;
Basic Operations
Following are the basic operations supported by an array.
Traverse Operation
Example
#include <stdio.h>
main() {
int i = 0, j = n;
}
When we compile and execute the above program, it produces the following result
−
Output
LA[0] = 1
LA[1] = 3
LA[2] = 5
LA[3] = 7
LA[4] = 8
Insertion Operation
Insert operation is to insert one or more data elements into an array. Based on the
requirement, a new element can be added at the beginning, end, or any given index
of array.
Example
#include <stdio.h>
main() {
n = n + 1;
while( j >= k) {
LA[j+1] = LA[j];
j = j - 1;
LA[k] = item;
When we compile and execute the above program, it produces the following result
−
Output
LA[0] = 1
LA[1] = 3
LA[2] = 5
LA[3] = 7
LA[4] = 8
LA[0] = 1
LA[1] = 3
LA[2] = 5
LA[3] = 10
LA[4] = 7
LA[5] = 8
Deletion Operation
Deletion refers to removing an existing element from the array and re-organizing
all elements of an array.
Example
#include <stdio.h>
void main() {
int k = 3, n = 5;
int i, j;
j = k;
while( j < n) {
LA[j-1] = LA[j];
j = j + 1;
n = n -1;
}
When we compile and execute the above program, it produces the following result
−
Output
LA[0] = 1
LA[1] = 3
LA[2] = 5
LA[3] = 7
LA[4] = 8
LA[0] = 1
LA[1] = 3
LA[2] = 7
LA[3] = 8
Binary search in C
Binary search in C language to find an element in a sorted array. If the array isn't
sorted, you must sort it using a sorting technique such as merge sort. If the element
to search is present in the list, then we print its location. The program assumes that
the input numbers are in ascending order.
#include <stdio.h>
int main()
scanf("%d", &n);
scanf("%d", &array[c]);
scanf("%d", &search);
first = 0;
last = n - 1;
middle = (first+last)/2;
first = middle + 1;
break;
else
last = middle - 1;
return 0;
Sorting
In simple word, sorting means arranging the given elements or data in an ordered
sequence. The main purpose of sorting is to easily & quickly locate an element in a
sorted list & design an efficient algorithm around
#include <stdio.h>
void main()
int i,j,n,a[100],temp,p,q,temp1;
scanf("%d",&n) ;
for(i=0;i<n;i++)
scanf("%d",&a[i]) ;
for(j=i+1;j<n;j++) { if(a[i]>a[j])
temp=a[i];
a[i]=a[j];
a[j]=temp;
for(i=0;i<n;i++)
printf("%d ",a[i]) ;
for(q=p+1;q<n;q++)
if(a[p]<a[q])
temp1=a[p];
a[p]=a[q];
a[q]=temp1;
}
}
for(p=0;p<n;p++)
printf("%d ",a[p]) ;
Output:-
12579
Multidimensional Arrays
• Multi-dimensional arrays are declared by providing more than one set of
square [ ] brackets after the variable name in the declaration statement.
• One dimensional arrays do not require the dimension to be given if the array
is to be completely initialized. By analogy, multi-dimensional arrays do not
require the first dimension to be given if the array is to be completely
initialized. All dimensions after the first must be given in any case.
• For two dimensional arrays, the first dimension is commonly considered to
be the number of rows, and the second dimension the number of columns.
We will use this convention when discussing two dimensional arrays.
• Two dimensional arrays are considered by C/C++ to be an array of ( single
dimensional arrays ). For example, "int numbers[ 5 ][ 6 ]" would refer to a
single dimensional array of 5 elements, wherein each element is a single
dimensional array of 6 integers. By extension, "int numbers[ 12 ][ 5 ][ 6 ]"
would refer to an array of twelve elements, each of which is a two
dimensional array, and so on.
• Another way of looking at this is that C stores two dimensional arrays by
rows, with all elements of a row being stored together as a single unit.
Knowing this can sometimes lead to more efficient programs.
• Multidimensional arrays may be completely initialized by listing all data
elements within a single pair of curly {} braces, as with single dimensional
arrays.
• It is better programming practice to enclose each row within a separate
subset of curly {} braces, to make the program more readable. This is
required if any row other than the last is to be partially initialized. When
subsets of braces are used, the last item within braces is not followed by a
comma, but the subsets are themselves separated by commas.
• Multidimensional arrays may be partially initialized by not providing
complete initialization data. Individual rows of a multidimensional array
may be partially initialized, provided that subset braces are used.
• Individual data items in a multidimensional array are accessed by fully
qualifying an array element. Alternatively, a smaller dimensional array may
be accessed by partially qualifying the array name. For example, if "data"
has been declared as a three dimensional array of floats, then data[ 1 ][ 2 ][ 5
] would refer to a float, data[ 1 ][ 2 ] would refer to a one-dimensional array
of floats, and data[ 1 ] would refer to a two-dimensional array of floats. The
reasons for this and the incentive to do this relate to memory-management
issues that are beyond the scope of these notes.
#include <stdio.h>
int b[ 2 ][ 3 ] = { { 1, 2, 3 }, { 3, 2, 1 } };
return 0;
For example: The string "home" contains 5 characters including the '\0' character
which is automatically added by the compiler at the end of the string.
String Handling Functions:
C language supports a large number of string handling functions that can be used
to carry out many of the string manipulations. These functions are packaged in the
string.h library. Hence, you must include string.h header file in your programs to
use these functions.
The following are the most commonly used string handling functions.
Method Description
#include <stdio.h>
#include <string.h>
int main () {
char str3[12];
int len ;
strcpy(str3, str1);
len = strlen(str1);
return 0;
When the above code is compiled and executed, it produces the following result −
strcpy( str3, str1) : Hello
strlen(str1) : 10
Array of Strings
What is an Array of String?
scanf( ) is the input function with %s format specifier to read a string as input from
the terminal. But the drawback is it terminates as soon as it encounters the space.
To avoid this gets( ) function which can read any number of strings including
white spaces.
puts() is used to display a string contained in a string variable . It also adds a new
line character to the end of the string
puts(string variable);
Eg. puts(str);
Sting is an array of characters terminated with the special character known as the
null character (“\0”).
Syntax
datatype name_of_the_array[size_of_elements_in_array];
char str_name[size];
Example
Str_name is the string name and the size defines the length of the string (number of
characters).
Syntax
char str_name[size][max];
Syntax
Syntax
From the given syntax there are two subscripts first one is for how many strings to
declare and the second is to define the maximum length of characters that each
string can store including the null character. C concept already explains that each
character takes 1 byte of data while allocating memory, the above example of
syntax occupies 2 * 6 =12 bytes of memory.
Now for two-dimensional arrays, we have the following syntax and memory
allocation. For this, we can take it as row and column representation (table format).
char str_name[size][max];
In this table representation, each row (first subscript) defines as the number of
strings to be stored and column (second subscript) defines the maximum length of
the strings.
Syntax:
#include<stdio.h>
int main()
char names[3][20];
int i;
for(i=0;i<3;i++)
for(i=0;i<3;i++)
printf(“\n%s”,names[i]);
return (0);
Output
Lovejot
Ajay
Amit
Ajay
Amit
We need to add the null character '\0' at the end of the array by ourself whereas, it
is appended internally by the compiler in the case of the character array.
The string literal cannot be reassigned to another set of characters whereas, we can
reassign the characters of the array.
Way-1
.
.
Way-2
. . .}
Way-3
Note :
in C, we must pass size of array as a parameter. Size may not be needed only in
case of ‘\0’ terminated character arrays, size can be determined by checking end of
string character.
Example 1:
#include <stdio.h>
int i;
// Driver program
int main()
fun(arr, n);
return 0;
Example 2:
#include <stdio.h>
void fun(int arr[], unsigned int n)
int i;
// Driver program
int main()
fun(arr, n);
return 0;
Example 3:
#include <stdio.h>
#include <string.h>
void fun(char *arr)
int i;
// Driver program
int main()
fun(arr);
return 0;
}
Passing a 2D array as a parameter in C
Just like a 1-D array, when a 2-D array is passed to a function, the changes made
by function effect the original array.
when a 2-D is passed to a function it is optional to specify the size of the left most
dimensions. So if we have an array of 2 rows and 3 dimensions then it can be
passed to a function in the following two ways:
1st way:
// statements;
2nd way:
// statements;
}
2-D arrays are stored in row-major order i.e first row 0 is stored, then next to it row
1 is stored and so on. Therefore in C, a 2-D array is actually a 1-D array in which
each element is itself a 1-D array. Since the name of the array points to the 0th
element of the array. In the case of a 2-D array, 0th element is an array.
Hence we can also declare a function where the formal argument is of type pointer
to an array.
3rd way:
// statements;
Essentially in all the three cases discussed the type of the variable a is a pointer to
an array of 3 integers, they differ only in the way they are represented.
Example 1:
#include <stdio.h>
const int N = 3;
int i, j;
int main()
print(arr, 3);
return 0;
}
Output
123456789
Example 2:
#include <stdio.h>
int i, j;
int main()
int m = 3, n = 3;
return 0;
}
Output
123456789
Example 3:
#include <stdio.h>
const int M = 3;
int i, j;
int main()
print(arr);
return 0;
}
Output
123456789
String Handling Without Using String Functions
We can reverse a given string by simply swapping ith character from the start and
ith character from the end of the string. Each pair of characters is only swapped
once. If we swap a pair twice then we will obtain the same string.
Steps
2. Set i = 0 and j = N – 1
• Swap(string[i] , string[j])
• ++i
• –j
We will implement our own strlen() function. In C/C++, every string ends with a
null character ‘\0’. To calculate the size of the string, we will traverse each
character of the array until we reach ‘\0’ and use a variable ‘count’ to count the
number of characters in the string.
#include<stdio.h>
int count = 0;
++count;
} return count;
char temp;
int i, j, n;
n = length(string);
temp = string[j];
string[j] = string[i];
string[i] = temp;
}
int main()
char string[100];
scanf("%s", string);
reverse(string);
Here we are giving one string in input and then with the help of for loop we
transfer the content of first array to the second array.
// CPP program to copy one string to other
#include <stdio.h>
int main()
s2[i] = s1[i];
}
s2[i] = '\0';
return 0;
}
Output:
string s1 : GeeksforGeeks
String s2 : GeeksforGeeks
If string are equal then print “Equal strings” else print “Unequal strings”.
Examples:
There are three possible cases occur when we compare two strings:
1.Both the strings are the same means difference of ASCII value between
both the strings is 0.
2.Both the strings are different means ASCII value of first not matching character
in the first string is less than the second string then the difference
between both the strings is (<0).
3.Both the strings are different means ASCII value of first not matching character
in the first string is greater than the second string then the difference
between both the strings is (>0).
Based on the above three conditions, the idea is to compare each character of the
given strings one by one whenever condition 2 or 3 occurs then print “Unequal
strings” else print “Equal strings”.
#include <stdio.h>
int flag = 0;
if (*x == *y) {
x++;
y++;
|| *x != *y) {
flag = 1;
printf("Uequal Strings\n");
break;
if (flag == 0) {
printf("Equal Strings\n");
// Driver Code
int main(void)
// Function Call
compareStrings(s1, s2);
return 0;
}
MODULE 4
Pointer
A pointer is a variable whose value is the address of another variable, i.e., direct
address of the memory location. Like any variable or constant, you must declare a
pointer before using it to store any variable address.
Declaring a pointer
The general form of a pointer variable declaration is −
type *var-name;
The pointer in c language can be declared using * (asterisk symbol). It is also known
as indirection pointer used to dereference a pointer.
Pointer Example
An example of using pointers to print the address and value is given below.
As you can see in the above figure, pointer variable stores the address of number
variable, i.e., fff4. The value of number variable is 50. But the address of pointer
variable p is aaa3.
By the help of * (indirection operator), we can print the value of pointer variable
p.
Example
#include<stdio.h>
int main(){
int number=50;
int *p;
p=&number; //stores the address of number variable
printf("Address of p variable is %x \n",p);
printf("Value of p variable is %d \n",*p);
return 0;
}
Output
Pointer to array
int arr[10];
int *p[10]=&arr; // Variable p of type pointer is pointing to the
address of an integer array arr.
Pointer to a function
void show (int);
void(*p)(int) = &display; // Pointer p is pointing to the address
of a function
Advantage of pointer
1) Pointer reduces the code and improves the performance, it is used to retrieving
strings, trees, etc. and used with arrays, structures, and functions.
3) It makes you able to access any memory location in the computer's memory.
Usage of pointer
Pointers in c language are widely used in arrays, functions, and structures. It reduces
the code and improves the performance.
The address of operator '&' returns the address of a variable. But, we need to use %u
to display the address of a variable.
The type of the pointer and the variable whose address is contained in the pointer
must be of same type.
float *q;
p= &a; /* valid */
q= &a; /* invalid */
Example
#include<stdio.h>
int main(){
int number=50;
printf("value of number is %d, address of number is %u",number,&number);
return 0;
}
Output
A pointer that is not assigned any value but NULL is known as the NULL pointer.
If you don't have any address to be specified in the pointer at the time of declaration,
you can assign NULL value. It will provide a better approach.
int *p=NULL;
VOID Pointer
A void pointer is a pointer that has no associated data type with it. A void pointer
can hold address of any type and can be typcasted to any type.
int a = 10;
char b = 'x';
Advantage of void pointers: malloc() and calloc() return void * type and this allows
these functions to be used to allocate memory of any data type (just because of void
*)
int main(void)
{
// Note that malloc() returns void * which can be
// typecasted to any type like int *, char *, ..
int *x = malloc(sizeof(int) * n);
}
Difference between void and Null Pointer
A null pointer is basically a null value assigned to a pointer of any data type
whereas a void pointer is a data type which remains void as long as an address of a
data type is not assigned to it.
The data type of the pointer is nothing but the type of data stored at the memory
location where the pointer is pointed. When you are not sure about the type of data
that is going to store at a particular memory location, you need to create the void
pointer.
Null pointer does not contain a reference of any variable/value. Hence we may state
that it has a NULL as its value making it a null pointer.
Void pointer is always of type void *
Mainly such pointers are used for dynamic memory allocations (using malloc(),
calloc() and realloc() functions) , where memory block reserved is pointer to by a
void pointer and as the pointer value is returned it has to be explicitly type casted
to a particular desired type.
Operations on pointers
We can perform arithmetic operations on the pointers like addition, subtraction, etc.
However, as we know that pointer contains the address, the result of an arithmetic
operation performed on the pointer will also be a pointer if the other operand is of
type integer. In pointer-from-pointer subtraction, the result will be an integer value.
Following arithmetic operations are possible on the pointer :
o Increment
o Decrement
o Addition
o Subtraction
o Comparison
Incrementing Pointer
If we increment a pointer by 1, the pointer will start pointing to the immediate next
location. This is somewhat different from the general arithmetic since the value of
the pointer will get increased by the size of the data type to which the pointer is
pointing.
We can traverse an array by using the increment operation on a pointer which will
keep pointing to every element of the array, perform some operation on that, and
update itself in a loop.
32-bit
64-bit
#include<stdio.h>
int main(){
int number=50;
int *p;//pointer to int
p=&number;//stores the address of number variable
printf("Address of p variable is %u \n",p);
p=p+1;
printf("After increment: Address of p variable is %u \n",p); // in our case, p will
get incremented by 4 bytes.
return 0;
}
Output
Output
64-bit
#include <stdio.h>
void main(){
int number=50;
int *p;//pointer to int
p=&number;//stores the address of number variable
printf("Address of p variable is %u \n",p);
p=p-1;
printf("After decrement: Address of p variable is %u \n",p); // P will now point t
o the immidiate previous location.
}
Output
We can add a value to the pointer variable. The formula of adding value to pointer
is given below:
64-bit
#include<stdio.h>
int main(){
int number=50;
int *p;//pointer to int
p=&number;//stores the address of number variable
printf("Address of p variable is %u \n",p);
p=p+3; //adding 3 to pointer variable
printf("After adding 3: Address of p variable is %u \n",p);
return 0;
}
Output
As you can see, the address of p is 3214864300. But after adding 3 with p variable,
it is 3214864312, i.e., 4*3=12 increment. Since we are using 64-bit architecture, it
increments 12. But if we were using 32-bit architecture, it was incrementing to 6
only, i.e., 2*3=6. As integer value occupies 2-byte memory in 32-bit OS.
Pointer Subtraction
Like pointer addition, we can subtract a value from the pointer variable. Subtracting
any number from a pointer will give an address. The formula of subtracting value
from the pointer variable is given below:
64-bit
#include<stdio.h>
int main(){
int number=50;
int *p;//pointer to int
p=&number;//stores the address of number variable
printf("Address of p variable is %u \n",p);
p=p-3; //subtracting 3 from pointer variable
printf("After subtracting 3: Address of p variable is %u \n",p);
return 0;
}
Output
You can see after subtracting 3 from the pointer variable, it is 12 (4*3) less than the
previous address value.
#include<stdio.h>
void main ()
{
int i = 100;
int *p = &i;
int *temp;
temp = p;
p = p + 3;
printf("Pointer Subtraction: %d - %d = %d",p, temp, p-temp);
}
Output
Pointer Subtraction: 1030585080 - 1030585068 = 3
Illegal arithmetic with pointers
There are various operations which can not be performed on pointers. Since, pointer
stores address hence we must ignore the operations which may lead to an illegal
address, for example, addition, and multiplication. A list of such operations is given
below.
Pointer to Pointer
A pointer to a pointer is a form of multiple indirection, or a chain of pointers.
Normally, a pointer contains the address of a variable. When we define a pointer to
a pointer, the first pointer contains the address of the second pointer, which points
to the location that contains the actual value as shown below.
#include <stdio.h>
int main () {
int var;
int *ptr;
int **pptr;
var = 3000;
/* take the address of var */
ptr = &var;
/* take the address of ptr using address of operator & */
pptr = &ptr;
/* take the value using pptr */
printf("Value of var = %d\n", var );
printf("Value available at *ptr = %d\n", *ptr );
printf("Value available at **pptr = %d\n", **pptr);
return 0;
}
When the above code is compiled and executed, it produces the following result −
Value of var = 3000
Value available at *ptr = 3000
Value available at **pptr = 3000
Call by value
o In call by value method, the value of the actual parameters is copied into the
formal parameters. In other words, we can say that the value of the variable is
used in the function call in the call by value method.
o In call by value method, we can not modify the value of the actual parameter
by the formal parameter.
o In call by value, different memory is allocated for actual and formal
parameters since the value of the actual parameter is copied into the formal
parameter.
o The actual parameter is the argument which is used in the function call
whereas formal parameter is the argument which is used in the function
definition.
main()
{ int a,b;
fun1(a,b);
#include <stdio.h>
void swap(int , int); //prototype of the function
int main()
{
int a = 10;
int b = 20;
printf("Before swapping the values in main a = %d, b = %d\n",a,b); // printin
g the value of a and b in main
swap(a,b);
printf("After swapping values in main a = %d, b = %d\n",a,b); // The value of
actual parameters do not change by changing the formal
parameters in call by value, a = 10, b = 20
}
void swap (int a, int b)
{
int temp;
temp = a;
a=b;
b=temp;
printf("After swapping values in function a = %d, b = %d\n",a,b); //
Formal parameters, a = 20, b = 10
}
Output
Before swapping the values in main a = 10, b = 20
After swapping values in function a = 20, b = 10
After swapping values in main a = 10, b = 20
Call by reference
o In call by reference, the address of the variable is passed into the function call
as the actual parameter.
o The value of the actual parameters can be modified by changing the formal
parameters since the address of the actual parameters is passed.
o In call by reference, the memory allocation is similar for both formal
parameters and actual parameters. All the operations in the function are
performed on the value stored at the address of the actual parameters, and the
modified value gets stored at the same address.
main()
{ int a,b;
fun1(&a, &b);
#include <stdio.h>
void swap(int *, int *); //prototype of the function
int main()
{
int a = 10;
int b = 20;
printf("Before swapping the values in main a = %d, b = %d\n",a,b); // printin
g the value of a and b in main
swap(&a,&b);
printf("After swapping values in main a = %d, b = %d\n",a,b); // The values o
f actual parameters do change in call by reference, a = 10, b = 20
}
void swap (int *a, int *b)
{
int temp;
temp = *a;
*a=*b;
*b=temp;
printf("After swapping values in function a = %d, b = %d\n",*a,*b);
// Formal parameters, a = 20, b = 10
}
Output
Before swapping the values in main a = 10, b = 20
After swapping values in function a = 20, b = 10
After swapping values in main a = 20, b = 10
A copy of the value is passed into the An address of value is passed into the
function function
Changes made inside the function is Changes made inside the function validate
limited to the function only. The values of outside of the function also. The values of the
the actual parameters do not change by actual parameters do change by changing the
changing the formal parameters. formal parameters.
Actual and formal arguments are created Actual and formal arguments are created at
at the different memory location the same memory location
Pointer And One-Dimensional Arrays
An array is a set of consecutive locations, having a common name and each location is identified
by an index number.
The name of the array is the beginning address of the array, called the base address of the array.
ie, it is the address of the first element. The array name is referred to as an address constant. The
array name is really a pointer to the 1st element in the array.
Both a and &a[0] is the same ie., base address(2010). Array name can be used as a pointer and
an integer value to represent the offset from the base address.
Address Value
&a[0] a+0 *(a+0) a[0] 11
&a[1] a+1 *(a+1) a[1] 12
&a[2] a+2 *(a+2) a[2] 13
In general
a+i denotes address of ith element
*(a+i) denotes the value at the address(a+i) which is same as a[i]
The address of an array cannot be altered using expressions like ++a.
The subscript notation is converted by compiler to pointer notation. So, if pointer notation is
used in programs , the programs work faster since no conversion is needed.
Pointer To an Array
int (*x) [20] – means x is defined to be a pointer to a group of contiguous , 1 D array, 20 element
integer arrays .
x points to the 1st 20 element array which is the 0th row of the original 2D array.
x+1 points to the 2nd 20 element array which is the 1st row of the original 2D array and so on.
In this example the pointer to array (ptr) incremented is shifted forward by 10 bytes which is the
base size .
*p gives the value 3, but *ptr gives 3000 which is the base address of array to which it points.
main()
{ int *p , (*ptr)[5], arr[5];
p=arr;
ptr=arr;
printf(“p= %u ptr= %u\n”, p, ptr);
p++;
ptr++;
printf(“p= %u ptr= %u”, p, ptr);
}
Output
p= 3000 ptr=3000
p= 3002 ptr=3010
• str being name of array is a constant pointer and the elements of the array
are as initialized.
• The string constant “Chennai “ is allocated space(8 bytes) somewhere in
memory and the starting address of this block is assigned to ptr.
• str always contains the same address, whereas ptr can contain any other
address
• . Eg. ptr=“ Delhi”;
Array of pointers to strings
• Array of pointers to string is array of char pointers, each pointer pointing to
a string. Each element of this array contains the base address of a string.
• char *arrp[]= {“white”,”red”, “green”, “yellow”, “blue”};
• The size can be specified, but here not specified and taken from the no.of
initializers
Program to sort strings alphabetically using array of pointers to strings
Pointer to Pointer (Multiple Indirection)
A pointer to a pointer is a form of multiple indirection or a chain of pointers.
Normally, a pointer contains the address of a variable. When we define a pointer to
a pointer, the first pointer contains the address of the second pointer, which points
to the location that contains the actual value as shown below.
int main ()
{
int var;
int *ptr;
int **pptr;
var = 3000;
ptr = &var;
pptr = &ptr;
printf( "Value of var : %d\n",var);
printf ( "Value available at *ptr : %d\n",*ptr);
printf ("Value available at **pptr : %d",**pptr );
return 0;
}
• The standard C library has built in library functions for dealing with
dynamic memory allocation. The prototypes of those functions are included in
header files alloc.h and stdlib.h
Syntax is
ptr= (data_type*)malloc(size);
where size is no.of bytes to be allocated and ptr is a pointer of type data_type,
which collects the address of the 1st byte of the memory allocated . The memory
block allocated will have garbage values. If allocation is unsuccessful, the function
returns NULL
• calloc – allocates multiple blocks of memory, all of which are of same size
and returns pointer to the 1st byte of the first block.
where n is the no.of blocks to be allocated and size is the no.of bytes in each
block and ptr is a pointer of type data_type, which collects the address of the 1st
byte of the first memory block allocated . The memory allocated will contain zeros.
If realloc cannot make the old block of memory bigger ‘in place’ , it reallocates
to a new location where enough space is available and returns the address to ptr.
Data in the old block will also be shifted to the new block.
where ptr is the pointer to the 1st byte of the block to be released. The memory
block is returned back to the free list within the heap.
Rearranging strings (dynamic allocation applied) (max of twenty strings each of
length 15 characters)
main()
{ char *x[20] , *temp; /* max of 20 ptrs*/
int i, j, n;
printf(“enter no.of strings”); scanf(“%d”, &n); for(i=0;i<n;i++)
{ /* allocate memory */
x[i]= (char*) malloc(15 *sizeof(char)) printf(“enter string”);
gets(x[i]);
}
Defining a Structure
To define a structure, you must use the struct statement. The struct statement
defines a new data type, with more than one member. The format of the struct
statement is as follows −
struct [structure tag] {
member definition;
member definition;
...
member definition;
} [one or more structure variables];
The structure tag is optional and each member definition is a normal variable
definition, such as int i; or float f; or any other valid variable definition. At the
end of the structure's definition, before the final semicolon, you can specify
one or more structure variables but it is optional. Here is the way you would
declare the Book structure −
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
} b1,b2;
Or
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
};
The variables b1 and b2 can be used to access the values stored in the structure.
#include<stdio.h>
#include <string.h>
struct employee
{ int id;
char name[50];
float salary;
}e1,e2; //declaring e1 and e2 variables for structure
int main( )
{
//store first employee information
e1.id=101;
strcpy(e1.name, "Sonoo Jaiswal");//copying string into char array
e1.salary=56000;
Structure Initialization
Like a variable of any other datatype, structure variable can also be initialized
at compile time.
struct Patient
{
float height;
int weight;
int age;
};
or
Two variables of the same structure type can be copied the same way as
ordinary variables.
If e1 and e2 belong to the same type, then the following statement is valid.
e1 = e2, and e2 = e1;
However, the statements that are shown here:
e1 < e2; and e1 != e2; are not permitted.
C language doesn't permit any logical operations on structure variables.
We can compare two structure variables but comparison of members of a
structure can only be done individually.
Operations on structure
• Accessing members with dot operator e.empno=10; strcpy(e.name,
“Ram”);
• Assigning one structure variable to another of same type struct emp
e1,e2; e2=e1;
• Knowing the size of a structure variable using sizeof() operator
printf(“%d”, sizeof(e));
• Size of a structure is the sum of sizes of its members.
• Checking whether two structure variables of same type are equal or not
equal using == and != All members of 1st structure variable are checked
for equality with the corresponding members of 2nd variable and returns
one 1 if they are equal , otherwise 0. All members of 1st structure variable
are checked for inequality with the corresponding members of 2nd
variable and returns one 1 if they are unequal , otherwise 0.
Array of Structures
An array of structres in C can be defined as the collection of multiple structures
variables where each variable contains information about different entities.
The array of structures in C are used to store information about multiple
entities of different data types. The array of structures is also known as the
collection of structures.
Output:
▪ A structure can also contain array members just like normal members
such int, float
▪ We can declare an array if we need to store multiple values inside structure.
▪ Structure may include as many array members as we require.
▪ Syntax for declaring array within structure is not different than the
conventional syntax. The only difference is that it is declared inside the
structure.
▪ Since we need to store marks for six subjects, we have to use looping structure
but the same is not true for character array of one dimension.
#include "stdio.h"
#include "conio.h"
#include "string.h"
struct student
int rno;
float per;
};
void main()
{
struct student s1; // structure variable declaration
int tot = 0;
clrscr();
scanf(“%d”, &s1.rno);
gets(s1.name);
scanf(“%d”, &s1.mark[i]);
}
// calculate percentage
s1.per = tot/6 ;
printf(“\n%d”,s1.mark[i]);
getch();
#include <stdio.h>
#include <string.h>
int main( ) {
Book book;
return 0;
}
When the above code is compiled and executed, it produces the following
result −
Book title : C Programming
Book author : Nuha Ali
Book subject : C Programming Tutorial
Book book_id : 6495407
By separate structure
By Embedded structure
1) Separate structure
Here, we create two structures, but the dependent structure should be
used inside the main structure as a member. Consider the following
example.
struct Date
int dd;
int mm;
int yyyy;
};
struct Employee
int id;
char name[20];
}emp1;
As you can see, doj (date of joining) is the variable of type Date. Here
doj is used as a member in Employee structure. In this way, we can use
Date structure in many structures.
2) Embedded structure
The embedded structure enables us to declare the structure inside the
structure. Hence, it requires less line of codes but it can not be used in
multiple data structures. Consider the following example.
struct Employee
int id;
char name[20];
struct Date
int dd;
int mm;
int yyyy;
}doj;
}emp1;
e1.doj.dd
e1.doj.mm
e1.doj.yyyy
C Nested Structure example
#include <stdio.h>
#include <string.h>
struct Employee
int id;
char name[20];
struct Date
int dd;
int mm;
int yyyy;
}doj;
}e1;
int main( )
e1.id=101;
e1.doj.mm=11;
e1.doj.yyyy=2014;
return 0;
struct name {
member1;
member2;
};
int main()
#include <stdio.h>
struct person
int age;
float weight;
};
int main()
scanf("%d", &personPtr->age);
scanf("%f", &personPtr->weight);
printf("Displaying:\n");
return 0;
Now, you can access the members of person1 using the personPtr
pointer.
1. #include<stdio.h>
2. struct address
3. {
4. char city[20];
5. int pin;
6. char phone[14];
7. };
8. struct employee
9. {
10. char name[20];
11. struct address add;
12. };
13. void display(struct employee);
14. void main ()
15. {
16. struct employee emp;
17. printf("Enter employee information?\n");
18. scanf("%s %s %d %s",emp.name,emp.add.city, &emp.add.pin, emp.
add.phone);
19. display(emp);
20. }
21. void display(struct employee emp)
22. {
23. printf("Printing the details....\n");
24. printf("%s %s %d %s",emp.name,emp.add.city,emp.add.pin,emp.add.
phone);
25. }
#include <stdio.h>
struct student
{
int reg_no;
char name [20] ;
float percent;
);
void display(struct student) ;
int main (void)
{
struct student s;
printf ("Enter reg_no, name and percent \n");
scanf ("%d%s%f", &s.reg_no, s.name, &s.percent);
display (s) ;
return 0;
}
void display(struct student s)
{
printf ("%6d%15s%6.2f \nn, s.reg_no, s.name, s.percent) ;
}
struct node {
int data1;
char data2;
};
int main()
return 0;
}
Union
A union is a special data type available in C that allows to store different data
types in the same memory location. You can define a union with many
members, but only one member can contain a value at any given time. Unions
provide an efficient way of using the same memory location for multiple-
purpose.
Defining a Union
To define a union, you must use the union statement in the same way as you
did while defining a structure. The union statement defines a new data type
with more than one member for your program. The format of the union
statement is as follows −
union [union tag] {
member definition;
member definition;
...
member definition;
} [one or more union variables];
The union tag is optional and each member definition is a normal variable
definition, such as int i; or float f; or any other valid variable definition. At the
end of the union's definition, before the final semicolon, you can specify one
or more union variables but it is optional. Here is the way you would define a
union type named Data having three members i, f, and str −
union Data {
int i;
float f;
char str[20];
} data;
Now, a variable of Data type can store an integer, a floating-point number, or
a string of characters. It means a single variable, i.e., same memory location,
can be used to store multiple types of data. You can use any built-in or user
defined data types inside a union based on your requirement.
The memory occupied by a union will be large enough to hold the largest
member of the union. For example, in the above example, Data type will
occupy 20 bytes of memory space because this is the maximum space which
can be occupied by a character string. The following example displays the
total memory size occupied by the above union −
#include <stdio.h>
#include <string.h>
union Data {
int i;
float f;
char str[20];
};
int main( ) {
return 0;
}
When the above code is compiled and executed, it produces the following
result −
Memory size occupied by data : 20
int main( ) {
data.i = 10;
data.f = 220.5;
strcpy( data.str, "C Programming");
return 0;
}
When the above code is compiled and executed, it produces the following
result −
data.i : 1917853763
data.f : 4122360580327794860452759994368.000000
data.str : C Programming
Here, we can see that the values of i and f members of union got corrupted
because the final value assigned to the variable has occupied the memory
location and this is the reason that the value of str member is getting printed
very well.
Now let's look into the same example once again where we will use one
variable at a time which is the main purpose of having unions −
#include <stdio.h>
#include <string.h>
union Data {
int i;
float f;
char str[20];
};
int main( ) {
data.i = 10;
printf( "data.i : %d\n", data.i);
data.f = 220.5;
printf( "data.f : %f\n", data.f);
return 0;
}
When the above code is compiled and executed, it produces the following
result −
data.i : 10
data.f : 220.500000
data.str : C Programming
Here, all the members are getting printed very well because one member is
being used at a time.
{
int i;
float f;
double d;
};
struct stemp
int type;
char name[20];
union temp u;
};
Int reg_no;
Char name[20];
};
MODULE 5
1. Introduction to Files in C:
A File is a collection of data stored in the secondary memory. So far data was entered
into the programs through the keyboard. So Files are used for storing information that can be
processed by the programs. Files are not only used for storing the data, programs are also stored
in files. In order to use files, we have to learn file input and output operations. That is, how data
is read and how to write into a file.
A Stream is the important concept in C. The Stream is a common, logical interface to the
various devices that comprise the computer. So a Stream is a logical interface to a file. There are
two types of Streams, Text Stream and Binary Stream. A Text File can be thought of as a stream
of characters that can be processed sequentially. It can only be processed in the forward
direction.
2. Using Files in C:
To use a file four essential actions should be carried out. These are,
a. Declare a file pointer variable.
b. Open a file using the fopen() function.
c. Process the file using suitable functions.
d. Close the file using the fclose() and fflush() functions.
Mode Description
r Opens a text file in reading mode
Now, lets see the syntax for creation of a new file or opening a file
file = fopen(“file_name”, “mode”)
This is a common syntax for both opening and creating a file in C.
Parameters
file_name − It is a string that specifies the name of the file that is to be opened or created using
the fopen method. mode: It is a string (usually a single character ) that specifies the mode in
which the file is to be opened. There are various modes available to open a file in C, we will
learn about all of them later in this article.
Let’s see can example which will make the concept clear, Suppose we are opening a file named
hello.txt using the fopen function. The following will be the statement,
Now, let’s see all types of modes that are available for us to read or write a file in C, and see
code snippets that will show sample runs of the code.
Mode = “r” − open for reading, this mode will open the file for reading purpose only, i.e. the
contents can only be viewed, nothing else like edits can be done to it.
This mode cannot create a new file and open() returns NULL, if we try to create a new file using
this mode.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "r")){
printf("File opened successfully in read mode");
}
else
printf("The file is not present! cannot create a new file using r mode");
fclose(file);
return 0;
}
Output
File opened successfully in read mode
We have created a file named hello.txt in our current directory but if we try to access other file
then we will get “The file is not present! cannot create a new file using r mode” as output.
Mode = “rb” − open for reading in binary mode, this mode will open the file for reading in
binary mode only, i.e. the contents can only be viewed and nothing else like edits can be done to
it.
This mode cannot create a new file and open() returns NULL, if we try to create a new file using
this mode.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("program.txt", "rb")){
printf("File opened successfully in read mode");
}
else
printf("The file is not present! cannot create a new file using rb mode");
fclose(file);
return 0;
}
Output
The file is not present! cannot create a new file using rb mode
Mode = “w” − open for writing only, this mode will open the file if present in the current
directory for writing only i.e. reading operation cannot be performed. If the file is not present in
the current directory, the program will create a new file and open it for writing.
If we open a file that contains some text in it, the contents will be overwritten.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("helo.txt", "w")){
printf("File opened successfully in write mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in write mode or a new file is created
You can see here, we have tried to open file “helo.txt” which is not present in the directory, still
the function returned the success message because it has create a file named “helo.txt”.
Mode = “wb” − open for writing in binary mode, this mode will open the file if present in the
current directory for writing in binary mode i.e. reading operation cannot be performed. If the
file is not present in the current directory, the program will create a new file and open it for
writing in binary mode.
If we open a file that contains some text in it, the contents will be overwritten.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "wb")){
printf("File opened successfully in write in binary mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in write in binary mode or a new file is created
Mode = “a” − open for append only, this mode will open the file if present in the current
directory for writing only i.e. reading operation cannot be performed. If the file is not present in
the current directory, the program will create a new file and open it for writing. If we open a file
that contains some text in it, the contents will not be overwritten; instead the new text will be
added after the existing text in the file.
Example
Live Demo
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "a")){
printf("File opened successfully in append mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in append mode or a new file is created
Mode = “ab” − open for append in binary, this mode will open the file if present in the current
directory for writing in binary only i.e. reading operation cannot be performed. If the file is not
present in the current directory, the program will create a new file and open it for writing in
binary.
If we open a file that contains some text in it, the contents will not be overwritten; instead the
new text will be added after the existing text in the file.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "ab")){
printf("File opened successfully in append in binary mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in append in binary mode or a new file is created
Mode = “r+” − open for reading and writing both, this mode will open the file for both reading
and writing purposes i.e. both read and write operations can be performed to the file.
This mode cannot create a new file and open() returns NULL, if we try to create a new file using
this mode.
If we open a file that contains some text in it and write something, the contents will be
overwritten.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "r+")){
printf("File opened successfully in read and write both");
}
else
printf("The file is not present! cannot create a new file using r+ mode");
fclose(file);
return 0;
}
Output
File opened successfully in read and write both
We have created a file named hello.txt in our current directory but if we try to access another file
then we will get “The file is not present! cannot create a new file using r+ mode” as output.
Mode = “rb+” − open for reading in binary mode, this mode will open the file for reading in
binary mode only, i.e. the contents can only be viewed and nothing else like edits can be done to
it.
This mode cannot create a new file and open() returns NULL, if we try to create a new file using
this mode.
If we open a file that contains some text in it and write something, the contents will be
overwritten.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("program.txt", "rb+")){
printf("File opened successfully in read mode");
}
else
printf("The file is not present! cannot create a new file using rb+ mode");
fclose(file);
return 0;
}
Output
The file is not present! cannot create a new file using rb+ mode
Mode = “w” − open for writing and reading, this mode will open the file if present in the current
directory for writing and reading operation both. If the file is not present in the current directory,
the program will create a new file and open it for reading and writing.
If we open a file that contains some text in it, the contents will be overwritten.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("helo.txt", "w+")){
printf("File opened successfully in read-write mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in read-write mode or a new file is created
You can see here, we have tried to open file “helo.txt” which is not present in the directory, still
the function returned the success message because it has create a file named “helo.txt”.
Mode = “wb+” : open for writing and reading in binary mode, this mode will open the file if
present in the current directory for writing and reading in
binary mode. If the file is not present in the current directory, the program will create a new file
and open it for reading and writing in binary mode. If we open a file that contains some text in it,
the contents will be overwritten.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "wb+")){
printf("File opened successfully in read-write in binary mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in read-write in binary mode or a new file is created
Mode = “a+” − open for read and append, this mode will open the file if present in the current
directory for both reading and writing. If the file is not present in the current directory, the
program will create a new file and open it for reading and writing.
If we open a file that contains some text in it, the contents will not be overwritten; instead the
new text will be added after the existing text in the file.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "a+")){
printf("File opened successfully in read-append mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in read-append mode or a new file is created
Mode = “ab+” − open for read and append in binary, this mode will open the file if present in the
current directory for both reading and writing in binary. If the file is not present in the current
directory, the program will create a new file and open it for reading and writing in binary. If we
open a file that contains some text in it, the contents will not be overwritten; instead the new text
will be added after the existing text in the file.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "ab+")){
printf("File opened successfully in read-append in binary mode or a new file is created");
}
else
printf("Error!”);
fclose(file);
return 0;
}
Output
File opened successfully in read
Reading Data for from an existing file
We can read content of a file in c using the fscanf() and fgets() and fgetc() functions. All are used
to read contents of a file. Let’s see the working of each of the function −
fscanf()
The fscanf() function is used to read character set i.e strings from the file. It returns the EOF,
when all the content of the file are read by it.
Syntax
int fscanf(FILE *stream, const char *charPointer[])
Parameters
FILE *stream: the pointer to the opened file.
const char *charPointer[]: string of character.
Example
#include <stdio.h>
int main(){
FILE * file;
char str[500];
if (file = fopen("hello.txt", "r")){
while(fscanf(file,"%s", str)!=EOF){
printf("%s", str);
}
}
else
printf("Error!”);
fclose(file);
return 0;
}
Output
Helloworld
fgets()
The fget() function in C is used to read string from the stream.
Syntax
char* fgets(char *string, int length, FILE *stream)
Parameter
char *string: It is a string which will store the data from the string.
int length: It is an int which gives the length of string to be considered.
FILE *stream: It is the pointer to the opened file.
Example
#include <stdio.h>
int main(){
FILE * file;
char str[500];
if (file = fopen("hello.txt", "r")){
printf("%s", fgets(str, 50, file));
}
fclose(file);
return 0;
}
Output
Hello world
fgetc()
The fgetc() function in C is used to return a single character from the file. It gets a character from
the file and returns EOF at the end of file.
Syntax
char* fgetc(FILE *stream)
Parameter
FILE *stream: It is the pointer to the opened file.
Example
#include <stdio.h>
int main(){
FILE * file;
char str;
if (file = fopen("hello.txt", "r")){
while((str=fgetc(file))!=EOF)
printf("%c",str);
}
fclose(file);
return 0;
}
Output
Hello world
Writing Data to a file in C
We can write data to a file in C using the fprintf(), fputs(), fputc() functions. All are used to write
contents to a file.
fprintf()
The fprintf() function is used to write data to a file. It writes a set of characters in a file.
Syntax
int fprintf(FILE *stream, char *string[])
Parameters
FILE for *stream: It is the pointer to the opened file.
char *string[]: It is the character array that we want to write in the file.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "w")){
if(fprintf(file, "tutorials Point”) >= 0)
printf("Write operation successful");
}
fclose(file);
return 0;
}
Output
Write operation successful
fputf()
The fputf() function in C can be used to write to a file. It is used to write a line (character line) to
the file.
Syntax
int fputs(const char *string, FILE *stream)
Parameters
Constant char *string[]: It is the character array that we want to write in the file.
FILE for *stream: It is the pointer to the opened file.
Example
Live Demo
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "w")){
if(fputs("tutorials Point", file) >= 0)
printf("String written to the file successfully...");
}
fclose(file);
return 0;
}
Output
String written to the file successfully…
fputc()
The fputc() function is used to write a single character to the file.
Syntax
int fputc(char character , FILE *stream)
Parameters
char character : It is the character that we want to write in the file.
FILE for *stream: It is the pointer to the opened file.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "w")){
fputc('T', file);
}
fclose(file);
return 0;
}
Output
‘T’ is written to the file.
fclose()
The fclose() function is used to close the open file. We should close the file after performing
operations on it to save the operations that we have applied to it.
Syntax
fclose(FILE *stream)
Parameters
FILE for *stream: It is the pointer to the opened file.
Example
#include <stdio.h>
int main(){
FILE * file;
char string[300];
if (file = fopen("hello.txt", "a+")){
while(fscanf(file,"%s", string)!=EOF){
printf("%s", string);
}
fputs("world", file);
}
fclose(file);
return 0;
}
Output
Hello
File contains
Helloworld
5.Formatted input/output functions
Formatted console input/output functions are used to take one or more inputs from the user at
console and it also allows us to display one or multiple values in the output to the user at the
console.
Some of the most important formatted console input/output functions are -
Functions
scanf()
This function is used to read one or multiple inputs from the user at the console.
printf()
This function is used to display one or multiple values in the output to the user at the console.
sscanf()
This function is used to read the characters from a string and stores them in variables.
sprintf()
This function is used to read the values stored in different variables and store these values in a
character array.
7.Binary Files
A binary file is a file that uses all 8 bits of a byte for storing the information .It is the form which
can be interpreted and understood by the computer.
The only difference between the text file and binary file is the data contain in text file can be
recognized by the word processor while binary file data can’t be recognized by a word processor.
1.wb(write)
this opens a binary file in write mode.
SYNTAX:
fp=fopen(“data.dat”,”wb”);
2.rb(read)
this opens a binary file in read mode
SYNTAX:
fp=fopen(“data.dat”,”rb”);
3.ab(append)
this opens a binary file in a Append mode i.e. data can be added at the end of file.
SYNTAX:
fp=fopen(“data.dat”,”ab”);
4.r+b(read+write)
this mode opens preexisting File in read and write mode.
SYNTAX:
fp=fopen(“data.dat”,”r+b”);
5.w+b(write+read)
this mode creates a new file for reading and writing in Binary mode.
SYNTAX:
fp=fopen(“data.dat”,”w+b”);
6.a+b(append+write)
this mode opens a file in append mode i.e. data can be written at the end of file.
SYNTAX:
fp=fopen(“data.dat”,”a+b”);
Additional features of C
Enumeration
Enumeration is a user defined datatype in C language. It is used to assign names to the integral
constants which makes a program easy to read and maintain. The keyword “enum” is used to
declare an enumeration.
Here is the syntax of enum in C language,
enum enum_name{const1, const2, ....... };
The enum keyword is also used to define the variables of enum type. There are two ways to define
the variables of enum type as follows.
enum week{sunday, monday, tuesday, wednesday, thursday, friday, saturday};
enum week day;
For example:
In the above statement, we have declared the 's' variable of type status.
enum status{false,true} s;
In this case, the default value of false will be equal to 0, and the value of true will be equal to 1.
#include <stdio.h>
enum weekdays{Sunday=1,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday};
int main()
{
enum weekdays w; // variable declaration of weekdays type
w=Monday; // assigning value of Monday to w.
printf("The value of w is %d",w);
return 0;
}
Output
The enum is also used in a switch case statement in which we pass the enum variable in a switch
parenthesis. It ensures that the value of the case block should be defined in an enum.
o The enum names available in an enum type can have the same value.
o If we do not provide any value to the enum names, then the compiler will automatically
assign the default values to the enum names starting from 0.
o We can also provide the values to the enum name in any order, and the unassigned names
will get the default value as the previous one plus one.
o The values assigned to the enum names must be integral constant, i.e., it should not be of
other types such string, float, etc.
o All the enum names must be unique in their scope, i.e., if we define two enum having same
scope, then these two enums should have different enum names otherwise compiler will
throw an error.
Bitwise Operator
The bitwise operators are the operators used to perform the operations on the data at the bit-level.
When we perform the bitwise operations, then it is also known as bit-level programming. It
consists of two digits, either 0 or 1. It is mainly used in numerical computations to make the
calculations faster.
We have different types of bitwise operators in the C programming language. The following is the
list of the bitwise operators:
| Bitwise OR operator
0 1 0 1 1
1 0 0 1 1
1 1 1 1 1
Bitwise AND operator is denoted by the single ampersand sign (&). Two integer operands are
written on both sides of the (&) operator. If the corresponding bits of both the operands are 1, then
the output of the bitwise AND operation is 1; otherwise, the output would be 0.
For example,
We have two variables a and b. a =6; b=4; The binary representation of the above two variables are
given below: a = 0110 b = 0100 When we apply the bitwise AND operation in the above two varia
bles, i.e., a&b, the output would be: Result = 0100
Bitwise AND operator through the program.
#include <stdio.h>
int main() {
int a=6, b=14; // variable declarations
printf("The output of the Bitwise AND operator a&b is %d",a&b);
return 0;
}
In the above code, we have created two variables, i.e., 'a' and 'b'. The values of 'a' and 'b' are 6 and
14 respectively. The binary value of 'a' and 'b' are 0110 and 1110, respectively. When we apply
the AND operator between these two variables,
Bitwise OR operator
The bitwise OR operator is represented by a single vertical sign (|). Two integer operands are
written on both sides of the (|) symbol. If the bit value of any of the operand is 1, then the output
would be 1, otherwise 0.
For example,
We consider two variables, a = 23; b = 10; The binary representation of the above two variable
s would be: a = 0001 0111 b = 0000 1010 When we apply the bitwise OR operator in the above
two variables, i.e., a|b , then the output would be:
Result = 0001 1111
As we can observe from the above result that the bits of both the operands are compared one by
one; if the value of either bit is 1, then the output would be 1 otherwise 0.
Bitwise exclusive OR operator is denoted by (^) symbol. Two operands are written on both sides
of the exclusive OR operator. If the corresponding bit of any of the operand is 1 then the output
would be 1, otherwise 0.
For example,
As we can observe from the above result that the bits of both the operands are compared one by
one; if the corresponding bit value of any of the operand is 1, then the output would be 1 otherwise
0.
#include <stdio.h>
int main()
{
int a=12,b=10; // variable declarations
printf("The output of the Bitwise exclusive OR operator a^b is %d",a^b);
return 0;
}
Output
The output of the Bitwise exclusive OR operator a^b is 6
The arguments passed from command line are called command line arguments. These arguments
are handled by main() function.
To support command line argument, you need to change the structure of main() function as given
below.
int main(int argc, char *argv[] )
Here, argc counts the number of arguments. It counts the file name as the first argument.
The argv[] contains the total number of arguments. The first argument is the file name always.
Example
Example of command line arguments where we are passing one argument with file name.
#include <stdio.h>
void main(int argc, char *argv[] ) {
printf("Program name is: %s\n", argv[0]);
if(argc < 2)
{
printf("No argument passed through command line.\n");
}
else{
printf("First argument is: %s\n", argv[1]);
}
}
Macros
A macro is a segment of code which is replaced by the value of macro. Macro is defined by #define
directive. There are two types of macros:
1. Object-like Macros
2. Function-like Macros
Object-like Macros
The object-like macro is an identifier that is replaced by value. It is widely used to represent
numeric constants. For example:
#define PI 3.14
Here, PI is the macro name which will be replaced by the value 3.14.
Function-like Macros
Visit #define to see the full example of object-like and function-like macros.
C Predefined Macros
Output:
Time :10:12:32
Line :8
STDC :1
The macro is not less than similar to functions, but macro has built-in macro also. In C, the macro
is used to define any constant value or any variable with its value in the entire program that will
be replaced by this macro name, where macro contains the set of code that will be called when the
macro name is used in the program. The macro uses the “#define” directive to define the macro in
C programming language. This is very useful to save time and have less code writing.
Macro Caveats
⚫ Macro definitions are not stored in the object file. They are only active for the duration of a
single source file starting when they are defined and ending when they are undefined (using
#undef), redefined, or when the end of the source file is found.
⚫ Macro definitions you wish to use in multiple source files may be defined in an include file
which may be included in each source file where the macros are required.
⚫ When a macro with arguments is invoked, the macro processor substitutes the arguments into
the macro body and then processes the results again for additional macro calls. This makes
it possible, but confusing, to piece together a macro call from the macro body and from the
macro arguments.
⚫ Most experienced C programmers enclose macro arguments in parentheses when they are
used in the macro body. This technique prevents undesired grouping of compound
expressions used as arguments and helps avoid operator precedence rules overriding the
intended meaning of a macro.
⚫ While a macro may contain references to other macros, references to itself are not expanded.
Self-referencing macros are a special feature of ANSI Standard C in that the self-reference
is not interpreted as a macro call. This special rule also applies to indirectly self-referencing
macros (or macros that reference themselves through another macro).
Conditional Compilation (#if, #ifdef, #ifndef, #else, #elif, #endif, and defined)
Six directives are available to control conditional compilation. They delimit blocks of program
text that are compiled only if a specified condition is true. These directives can be nested. The
program text within the blocks is arbitrary and may consist of preprocessor directives, C
statements, and so on. The beginning of the block of program text is marked by one of three
directives:
⚫ #if
⚫ #ifdef
⚫ ifndef
Optionally, an alternative block of text can be set aside with one of two directives:
◆#else
◆#elif
The end of the block or alternative block is marked by the #endif directive.
If the condition checked by #if , #ifdef , or #ifndef is true (nonzero), then all lines between the
matching #else (or #elif ) and an #endif directive, if present, are ignored.
If the condition is false (0), then the lines between the #if , #ifdef , or #ifndef and
an #else , #elif , or #endif directive are ignored.