0% found this document useful (0 votes)
14 views204 pages

Learn C

The document provides an introduction to the C programming language, focusing on variables, their types, and how to declare, define, and use them. It covers basic data types, pointers, structures, and the use of the typedef keyword for simplifying structure definitions. Additionally, it explains the concept of constant variables and the initialization of structures, along with examples to illustrate these concepts.

Uploaded by

cragnolinitomas
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views204 pages

Learn C

The document provides an introduction to the C programming language, focusing on variables, their types, and how to declare, define, and use them. It covers basic data types, pointers, structures, and the use of the typedef keyword for simplifying structure definitions. Additionally, it explains the concept of constant variables and the initialization of structures, along with examples to illustrate these concepts.

Uploaded by

cragnolinitomas
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 204

Learn C

The C program structure:

#include<iostream> // this is called a header file

// this is the main function

int main () {

};

Chapter 1

Variables

A variable is a data structure that allows storing different kinds of values . variables are the
names you give to a specific computer's memory location .

Picture this like a little box where you want to store something and you label that box in order
to know what it contains.
As for a real world example, imagine you have a box where you want to store books its
genre and you also want to know how many are in there.
you’d possibly follow this approach you’d get a box and stick a label on it with the following
writing .

books of fiction

20

When you take that box for whatever purpose you know it contains 20 books belonging to
the fiction genre.

Let’s take that example and try to make it computer’s related :

// this is a variable called BooksOfFictionBox (represents the box labeled books of


fiction) which stores( represented by the equal sign “=” ) 20 fictional books
(quantity of book items)

BooksOfFictionBoxNumber= 20;
Let’s go through this example and make it work following a C syntax program :

A variable declaration and definition in C assumes the following syntax:

1. Type
2. Variable name
3. Value

1. The type relates to the kind of value you want to store:In the above example you use
the value 20 to indicate the number of books. this being provided , it can be deduced
that numbers are a value type.There are also many more types that will be later
explained throughout the chapter.

2. It’s just a way to give a name that describes best what the value is related to. In the
books case you use the name BooksOfFictionBoxNumber to denote that you’re going
to store the number of books of that genre.

3. The value itself is followed by a semicolon . In this case you assign the value 20.

Chapter 1

1. Variable Creation

The process I detailed before resumes how you can create variables. Nevertheless I’d like to
clarify two concepts that You’ll see quite often throughout the book:

1) Declaration : it creates a variable but assigns no value to it .

For example : int numberOfPencils; // this is a declaration

2) Definition/Initialization : assigning a value to a variable. Definition also called


initialization can be achieved according to different kinds of syntaxes.

a) Direct initialization : the assignment and declaration take place at the same
line of code.

int numberOfPencils = 10; // direct initialization


b) Definition after declaration: the definition takes place in a further step once
the variable has been declared.

int numberOfPencils; // variable declaration


numberOfPencils= 20//variable definition

2. Declaring and Defining variables of the same type:

1)

int numOne,numThree; // declares three integer variables


numOne=1;// assigns 1 therefore defines numOne to 1
numTwo=2;// assigns 2 therefore defines numTwo to 2

2)

int numOne,numThree=3 ;// declares numOne and declares and define


numThree to 3

3)

int numOne,numTwo;// declares both variables


numOne= numTwo= 1;// defines both variable to 1

3. Variable Reassignment

You can redefine a variable later in your program . You can assign a different value any
time. You’ll learn more about this topic in the Operators chapter.

For example:

// you define two int variables

int anInt=2;
int anotherInt= 1;

// to start using the variables you must not include the int type
anymore. the program already knows what kind of variable it is
dealing with.
nevertheless notice that both variables belong to the same type
(int).
anInt = anotherInt

//Now anInt holds the value of anotherInt.

anInt equals 1 ;
anotherInt equals 2;

4.Const variables

In the previous program it was explained how you can declare, define (also initialize and
assign ) and redefine (reassign) variables.
Const variables behave a little differently in terms of declaration , definition and
reassignment.

Let’s take a look :

a) To declare a const variable you must initialize it straight away.So you use the one
step definition :

// you´re using the const keyword before the type.

const int number =2;

b) You can't reassign any values later in the program . it yields an error when you run
the code..

const int number =3 ;

number = 2;

To conclude , what do you need a const variable for ? when you want to store values that
you dont later want to change along the program.

A simple C program explained :

Program description: it prints the BooksOfFictionBoxNumber value on the screen.

#include <iostream> // this is called a preprocessor directive. in


simple words it contains code ready to use so you don't have to
write everything from start to end yourself. simplifies your work by
providing ready used code .
// main is where all the code you write gets executed. if you dont
write inside main the program simply wont work.

int main (){

// this declares and defines a variable that stores an integer


number that’s why the type int is used.

int BooksOfFictionBoxNumber = 20;

// this prints the value contained in BooksOfFictionBoxNumber on the


screen. Printf() is a function ,a piece of code that performs an
operation. Its functionality is to print values. I’ll clear how it
works later on a chapter.

printf(“%d”,BooksOfFictionBoxNumber );

// indicates that the programs stops

return 0;

};

5. Variable Types

1) Basic Data Types

Previously I used the int type to give an example for creating a variable.
The list below shows the remaining data types.Declaration and definition
Data Types Examples :

char data type : char g = ‘g’;


int data type: int intNum = 1;
float data type: float floatNum= 12.236;
double data type : double doubleNum=17,723;

2) More Specific Data Types

In the table below you’ll see included some of the basic types with some modifications , the
value range (numbers that can be stored ) and the printf format specifier,which I’ll explain in
brevity). I’ll just give an explanation of the types not discussed beforehand.

If you pay attention there are some new keywords before the basic types:

a) short
b) long
c) unsigned/signed
These are called modifiers just like the const keyword but they affect the value range of the
basic types when used in combination.

a) Long and Short

1) Short reduces the range capacity in a half. So when you declare a variable
using the short modifier it takes half the storage capacity that a normal int:

A normal int takes 4 bytes of memory storage capacity.A short int takes 2 bytes of
memory storage capacity.

b) Long doubles the int memory storage capacity : An int data type takes 4 bytes of
memory storage.A long int takes 8.

c) Signed and Unsigned

1) signed means that the value range can include negative and positive numbers
including 0.

2) unsigned means that the value range can only include positive values including 0.
types by default are signed .They do not affect the memory storage capacity but it changes
the value range these variables can contain.

3. Format Specifiers

Format specifiers are placeholders that are replaced by the argument values supplied in the
printf() function between others.
In the format string section you add the format specifiers and in the arguments section you
add the values you want to print .
Remember that this function prints the arguments provided on the screen.
Each placeholder points to the corresponding argument in the exact same order they’re
included.
1) Format Specifier List

%d : it is used for displaying integers and short integers


%f : it’s used to display float and double types
%c: displays a single character
%u: displays unsigned characters, unsigned int and unsigned short int.
%lu: displays unsigned long int types
%ld: used for displaying long int types

Example :

#include <stdio.h>

int main () {

long int lampsQuantity =14;

// the function takes the lampsQuantity variable , reads its value


and displays it using the %ld placeholder

printf(“%ld”, lampsQuantity);

return 0;

4. POINTER VARIABLES

Pointers are a special kind of data type that lets you store another variable’s memory
address.
every variable gets assigned an address in the computer’s memory when you declare it .
You previously saw that an int variable will take 4 bytes of memory when you declare it. you
can get its memory address through the use of pointers . an address is the place where your
variable is stored.
1) The Declaration Syntax is as follows :

type * pointer_name ;

Example : int* number ;

2) Pointer Variable Definition:

First you need a variable of any kind to be pointed to:

int pencils= 3; // integer variable declaration and initialization.

Pointer assignment can be achieved according to the next two syntaxes:

a) Two steps assignment:

I) int *pointerToPencils ;

II) pointerToPencils = &pencils;

b) One step assignment

I) type * pointer_name1 = &variable_name;


Example: int *pointerToPencils =&pencils;

3) DEREFERENCING (Accessing The Value of The Pointed Variable )

To access the value stored in the variable Pencils through the pointerToPencils variable :

// this is called dereferencing . It prints the value holded by the


variable pencils.

Example:

*pointerToPencils

std::cout<< *pointerToPencils<< endl // equals 3

4. CONST POINTERS

Pointers can point to a const object, and the syntax is also


similar and intuitive to other const variables:

a) const type *pointer_name = &variable_name;

snippet:

int books=3; // int variables


int chapter=2; // int variables
const int *bookP= &books; // pointer variable

*bookP= 15; // error you cant modify the value but you can assign
the pointer to point to a different variable.

bookP=&chapter; // in this case you’re changing the address of bookP


to point to the variable chapter’s address.

5. Pointers To Const

a) type *const pointer_name = &variable_name;

Snippet :

int books= 3; // int variables


int chapter=2; // int variables

int *const bookP= &books;

bookP=&chapter; // this will throw an error since you cannot modify


the variable booksP points to.

bookP=22; // you cannot modify the value of books through bookP

Pointers resume table


C Compound Data Types

1. C structures

The structure in C is a user-defined data type that can be used to group items of possibly
different types into a single type. The struct keyword is used to define it. The items in the
structure are called its members(properties) and they can be of any valid data type.
1) C Structure Declaration

We can use the struct keyword to declare the structure in C using the following syntax:

Syntax

struct structure_name {
data_type member_name1;
data_type member_name1;
....
....
};

2) C Structure Definition

To use structure in our program, we have to define its instance. We can do that by creating
variables of the structure type. We can define structure variables using two methods:

a) Structure Variable Declaration with Structure Template


struct structure_name {
data_type member_name1;
data_type member_name1;
....
....
}variable1, varaible2, ...;

b) Structure Variable Declaration after Structure Template

// structure declared beforehand


struct structure_name variable1, variable2, .......;

3) Initialize Structure Members

Structure members cannot be initialized with the declaration. For example, the following C
program fails in the compilation.

struct Point
{
int x = 0; // COMPILER ERROR: cannot initialize members
here
int y = 0; // COMPILER ERROR: cannot initialize members
here
};

The reason for the above error is simple. When a datatype is declared, no memory is
allocated for it. Memory is allocated only when variables are created.
We can initialize structure members in 3 ways which are as follows:

a) Using Assignment Operator.


b) Using Initializer List.
c) Using Designated Initializer List.

a) Initialization using Assignment Operator

struct structure_name str;


str.member1 = value1;
str.member2 = value2;
str.member3 = value3;
.
.
.

b) Initialization using Initializer List

struct structure_name str = { value1, value2, value3 };


In this type of initialization, the values are assigned in sequential order as they are declared
in the structure template.

c) Initialization using Designated Initializer List


Designated Initialization allows structure members to be initialized in any order. This feature
has been added in the C99 standard.

struct structure_name str = { .member1 = value1, .member2 =


value2, .member3 = value3 };

The Designated Initialization is only supported in C but not in C++.

c) Access Structure Members

We can access structure members by using the ( . ) dot operator.

Syntax

structure_name.member1;
strcuture_name.member2;
In the case where we have a pointer to the structure, we can also use the arrow operator to
access the members.

Example of Structure in C

The following C program shows how to use structures


// C program to illustrate the use of structures
#include <stdio.h>

// declaring structure with name str1


struct str1 {
int i;
char c;
float f;
char s[30];
};

// declaring structure with name str2


struct str2 {
int ii;
char cc;
float ff;
} var; // variable declaration with structure template

// Driver code
int main()
{
// variable declaration after structure template
// initialization with initializer list and designated
// initializer list
struct str1 var1 = { 1, 'A', 1.00, "GeeksforGeeks" },var2;
struct str2 var3 = { .ff = 5.00, .ii = 5, .cc = 'a' };

// copying structure using assignment operator


var2 = var1;

printf("Struct 1:\n\ti = %d, c = %c, f = %f, s = %s\n",


var1.i, var1.c, var1.f, var1.s);
printf("Struct 2:\n\ti = %d, c = %c, f = %f, s = %s\n",
var2.i, var2.c, var2.f, var2.s);
printf("Struct 3\n\ti = %d, c = %c, f = %f\n", var3.ii,
var3.cc, var3.ff);

return 0;
}

Output
Struct 1:
i = 1, c = A, f = 1.000000, s = GeeksforGeeks
Struct 2:
i = 1, c = A, f = 1.000000, s = GeeksforGeeks
Struct 3
i = 5, c = a, f = 5.000000

4) Typedef for Structures

The typedef keyword is used to define an alias for the already existing datatype. In
structures, we have to use the struct keyword along with the structure name to define the
variables. Sometimes, this increases the length and complexity of the code. We can use the
typedef to define some new shorter name for the structure.

// C Program to illustrate the use of typedef with


// structures
#include <stdio.h>

// defining structure
struct str1 {
int a;
};

// defining new name for str1


typedef struct str1;

// another way of using typedef with structures


typedef struct str2 {
int x;
} str2;

int main()
{
// creating structure variables using new names
str1 var1 = { 20 };
str2 var2 = { 314 };
printf("var1.a = %d\n", var1.a);
printf("var2.x = %d", var2.x);

return 0;
}

Output
var1.a = 20
var2.x = 314

5) Nested Structures

C language allows us to insert one structure into another as a member. This process is
called nesting and such structures are called nested structures. There are two ways in which
we can nest one structure into another:

a. Embedded Structure Nesting

In this method, the structure being nested is also declared inside the parent structure.

Example

struct parent {
int member1;
struct member_str member2 {
int member_str1;
char member_str2;
...
}
...
}

b. Separate Structure Nesting

In this method, two structures are declared separately and then the member structure is
nested inside the parent structure.

Example

struct member_str {
int member_str1;
char member_str2;
...
}

struct parent {
int member1;
struct member_str member2;
...
}

One thing to note here is that the declaration of the structure should always be present
before its definition as a structure member. For example, the declaration below is invalid as
the struct mem is not defined when it is declared inside the parent structure.

struct parent {
struct mem a;
};

struct mem {
int var;
};

c. Accessing Nested Members

We can access nested Members by using the same ( . ) dot operator two times as shown:

str_parent.str_child.member;

Example:

// C Program to illustrate structure nesting along with


// forward declaration
#include <stdio.h>

// child structure declaration


struct child {
int x;
char c;
};

// parent structure declaration


struct parent {
int a;
struct child b;
};

// driver code
int main()
{
struct parent var1 = { 25, 195, 'A' };

// accessing and printing nested members


printf("var1.a = %d\n", var1.a);
printf("var1.b.x = %d\n", var1.b.x);
printf("var1.b.c = %c", var1.b.c);

return 0;
}

Output
var1.a = 25
var1.b.x = 195
var1.b.c = A

c. Structure Pointer in C

We can define a pointer that points to the structure like any other variable. Such pointers are
generally called Structure Pointers. We can access the members of the structure pointed by
the structure pointer using the ( -> ) arrow operator.

Example of Structure Pointer

// C program to illustrate the structure pointer


#include <stdio.h>

// structure declaration
struct Point {
int x, y;
};

int main()
{
struct Point str = { 1, 2 };

// p2 is a pointer to structure p1
struct Point* ptr = &str;

// Accessing structure members using structure pointer


printf("%d %d", ptr->x, ptr->y);

return 0;
}

Output
1 2
d. Self-Referential Structures

The self-referential structures in C are those structures that contain references to the same
type as themselves i.e. they contain a member of the type pointer pointing to the same
structure type.

Example of Self-Referential Structures

struct structure_name {
data_type member1;
data_type member2;
struct structure_name* str;
}
// C program to illustrate the self referential structures
#include <stdio.h>

// structure template
typedef struct str {
int mem1;
int mem2;
struct str* next;
}str;

// driver code
int main()
{
str var1 = { 1, 2, NULL };
str var2 = { 10, 20, NULL };

// assigning the address of var2 to var1.next


var1.next = &var2;

// pointer to var1
str *ptr1 = &var1;

// accessing var2 members using var1


printf("var2.mem1: %d\nvar2.mem2: %d", ptr1->next->mem1,
ptr1->next->mem2);

return 0;
}

Output

var2.mem1: 10
var2.mem2: 20
Such kinds of structures are used in different data structures such as to define the nodes of
linked lists, trees, etc.
}

e. Bit Fields

Bit Fields are used to specify the length of the structure members in bits. When we know the
maximum length of the member, we can use bit fields to specify the size and reduce memory
consumption.

Syntax of Bit Fields

struct structure_name {
data_type member_name: width_of_bit-field;
};

Example of Bit Fields

// C Program to illustrate bit fields in structures


#include <stdio.h>

// declaring structure for reference


struct str1 {
int a;
char c;
};

// structure with bit fields


struct str2 {
int a : 24; // size of 'a' is 3 bytes = 24 bits
char c;
};

// driver code
int main()
{
printf("Size of Str1: %d\nSize of Str2: %d",
sizeof(struct str1), sizeof(struct str2));
return 0;
}

Output

Size of Str1: 8
Size of Str2: 4
2. Unions

The Union is a user-defined data type in C language that can contain elements of the
different data types just like structure. But unlike structures, all the members in the C union
are stored in the same memory location. Due to this, only one member can store data at the
given instance.

Syntax of Union in C
The syntax of the union in C can be divided into three steps which are as follows:

2.1. C Union Declaration

In this part, we only declare the template of the union, i.e., we only declare the members’
names and data types along with the name of the union. No memory is allocated to the
union in the declaration.

union union_name {

datatype member1;

datatype member2;

...

};
Keep in mind that we have to always end the union declaration with a semi-colon.

2.2 Different Ways to Define a Union Variable

We need to define a variable of the union type to start using union members. There are two
methods using which we can define a union variable.

1) With Union Declaration


2) After Union Declaration

1) Defining Union Variable with Declaration

union union_name {

datatype member1;

datatype member2;

...

} var1, var2, ...;

2) Defining Union Variable after Declaration

union union_name var1, var2, var3...;

where union_name is the name of an already declared union.

3) Access Union Members

We can access the members of a union by using the ( . ) dot operator just like structures.

var1.member1;

where var1 is the union variable and member1 is the member of the union.

The above method of accessing the members of the union also works for the nested unions.

var1.member1.memberA;
Here,

● var1 is a union variable.

● member1 is a member of the union.

● memberA is a member of member1.

4) Initialization of Union in C

The initialization of a union is the initialization of its members by simply assigning the value
to it.

var1.member1 = some_value;

One important thing to note here is that only one member can contain some value at a
given instance of time.

Example of Union

// C Program to demonstrate how to use union


#include <stdio.h>

// union template or declaration


union un {
int member1;
char member2;
float member3;
};

// driver code
int main()
{

// defining a union variable


union un var1;

// initializing the union member


var1.member1 = 15;

printf("The value stored in member1 = %d",


var1.member1);

return 0;
}

Output
The value stored in member1 = 15

2.3 Size of Union

The size of the union will always be equal to the size of the largest member of the array.

All the less-sized elements can store the data in the same space without any overflow.

Example 1: C program to find the size of the union

// C Program to find the size of the union


#include <stdio.h>

// declaring multiple unions


union test1 {
int x;
int y;
} Test1;

union test2 {
int x;
char y;
} Test2;

union test3 {
int arr[10];
char y;
} Test3;

// driver code
int main()
{
// finding size using sizeof() operator
int size1 = sizeof(Test1);
int size2 = sizeof(Test2);
int size3 = sizeof(Test3);

printf("Sizeof test1: %d\n", size1);


printf("Sizeof test2: %d\n", size2);
printf("Sizeof test3: %d", size3);
return 0;
}

Output
Sizeof test1: 4
Sizeof test2: 4
Sizeof test3: 40

2.4 Difference between C Structure and C Union


The following table lists the key difference between the structure and union in C:

3. Enumeration (or enum)

is a user defined data type in C. It is mainly used to assign names to integral constants, the
names make a program easy to read and maintain.
enum State {Working = 1, Failed = 0};

The keyword ‘enum’ is used to declare new enumeration types in C and C++. Following is an
example of enum declaration.

// The name of enumeration is "flag" and the constant


// are the values of the flag. By default, the values
// of the constants are as follows:
// constant1 = 0, constant2 = 1, constant3 = 2 and
// so on.
enum flag{constant1, constant2, constant3, ....... };

1) Variables of type enum can also be defined in two ways:

a)

// In both of the below cases, "day" is


// defined as the variable of type week.

enum week{Mon, Tue, Wed};


enum week day;

b)

enum week{Mon, Tue, Wed} day;

// An example program to demonstrate working


// of enum in C

#include<stdio.h>
enum week{Mon, Tue, Wed, Thur, Fri, Sat, Sun};

int main()
{
enum week day;
day = Wed;
printf("%d",day);
return 0;
}

Output:
2
In the above example, we declared “day” as the variable and the
value of “Wed” is allocated to day, which is 2. So as a result, 2 is
printed.

Another example of enumeration is:

// Another example program to demonstrate working


// of enum in C
#include<stdio.h>

enum year{Jan, Feb, Mar, Apr, May, Jun, Jul,


Aug, Sep, Oct, Nov, Dec};

int main()
{
int i;
for (i=Jan; i<=Dec; i++){
printf("%d ", i);}
return 0;
}
Output:

0 1 2 3 4 5 6 7 8 9 10 11

In this example, the for loop will run from i = 0 to i = 11, as initially the value of i is Jan which
is 0 and the value of Dec is 11.

3.1 Interesting facts about initialization of enum.

1) Two enum names can have the same value. For example, in the following C program both
‘Failed’ and ‘Freezed’ have same value 0.

#include <stdio.h>
enum State {Working = 1, Failed = 0, Freezed = 0};

int main()
{
printf("%d, %d, %d", Working, Failed, Freezed);
return 0;}
chapter 3

1. SCOPE

The scope of a variable in C is the block or the region in the program where a variable is
declared, defined, and used. Outside this region, we cannot access the variable and it is
treated as an undeclared identifier.

1.1 Types of Scope Rules in

C scope rules can be covered under the following two categories:

a) Global Scope
b) Local Scope

Let’s discuss each scope rule with examples.

a) Global Scope in C

1. The global scope refers to the region outside any block or function.
2. The variables declared in the global scope are called global variables.
3. Global variables are visible in every part of the program.
4. Global is also called File Scope as the scope of an identifier starts at the
beginning of the file and ends at the end of the file.

Example :

// C program to illustrate the global scope


#include <stdio.h>

// variable declared in global scope

int global = 5;

// global variable accessed from


// within a function

void display()
{
printf("%d\n", global);
}

// main function

int main()
{
printf("Before change within main: ");
display();

// changing value of global


// variable from main function
printf("After change within main: ");
global = 10;
display();
}

Output
Before change within main: 5
After change within main: 10

Linkage of Variables in Global Scope

Global variables have external linkage by default. It means that the variables declared in the
global scope can be accessed in another C source file. We have to use the extern keyword
for that purpose.

Example of External Linkage


file1.c

// filename: file1.c

int a;

int main(void)
{
a = 2;
}

// filename: file2.c
// When this file is linked with file1.c, functions
// of this file can access a

extern int a;

int myfun()
{
printf("%d", a);
}

Output

Note: To restrict access to the current file only, global variables can be marked as static.

b) Local Scope in C

The local scope refers to the region inside a block or a function. It is the space enclosed
between the { } braces.

The variables declared within the local scope are called local variables.

Local variables are visible in the block they are declared in and other blocks nested inside
that block.

Local scope is also called Block scope.

Local variables have internal linkage.

// C program to illustrate the local scope


#include <stdio.h>

// Driver Code
int main()
{
{
int x = 10, y = 20;
{
// The outer block contains
// declaration of x and
// y, so following statement
// is valid and prints
// 10 and 20

printf("x = %d, y = %d\n", x, y);


{
// y is declared again,
// so outer block y is
// not accessible in this block
int y = 40;

// Changes the outer block


// variable x to 11
x++;

// Changes this block's


// variable y to 41
y++;

printf("x = %d, y = %d\n", x, y);


}

// This statement accesses


// only outer block's
// variables
printf("x = %d, y = %d\n", x, y);
}
}
return 0;
}

Output
x = 10, y = 20
x = 11, y = 41
x = 11, y = 20
Q1. What if the inner block itself has one variable with the same name?
If an inner block declares a variable with the same name as the variable declared by the
outer block, then the visibility of the outer block variable ends at the point of the declaration
by inner block.

Q2. What is the difference between the scope and lifetime?


The scope and lifetime of a variable are often confused with one another
● The scope of the variable is the region where it is valid to refer to the variable using
its name.

● The lifetime of the variable is the time between it is allocated memory and it is
deleted from the memory.

Q2. What about functions and parameters passed to functions?


A function itself is a block. Parameters and other local variables of a function follow the same
block scope rules.

Q3. Can variables of the block be accessed in another subsequent block?


No, a variable declared in a block can only be accessed inside the block and all inner blocks
of this block.

chapter 3

1. Introduction Loops and Functions

1) Functions
2) Loops

1) Functions
A sequence of program instructions that performs a specific task, packaged as a unit.
Just like variables you need to declare and define them but there’s also a further step which
is named calling.

a) Declaration
In a function declaration, we must provide the function name, its return type, and the number
and type of its parameters. A function declaration tells the compiler that there is a function
with the given name defined somewhere else in the program.

return_type name_of_the_function (parameter_1, parameter_2);


The parameter name is not mandatory while declaring functions. We can also declare the
function without using the name of the data variables.
b) Function Definition

The function definition consists of actual statements which are executed when the function is
called (i.e. when the program control comes to the function).
A C function is generally defined and declared in a single step because it always starts with
the function declaration so we do not need to declare it explicitly. The below example serves
as both a function definition and a declaration.

c) Function Call

A function call is a statement that instructs the compiler to execute the function. We use the
function name and parameters in the function call.
In the below example, the first sum function is called and 10,30 are passed to the sum
function. After the function call sum of a and b is returned and control is also returned back
to the main function of the program.

Function call is necessary to bring the program control to the function definition. If not
called, the function statements will not be executed.
// Calling sum function and
// storing its value in add variable
int add = sum(10, 30);

printf("Sum is: %d", add);


return 0;
}
Output
Sum is: 40
As we noticed, we have not used explicit function declaration. We simply defined and called
the function.

d) function with Arguments

Function Arguments (also known as Function Parameters) are the data that is passed to a
function. This is shown in the previous example . The sum function is passed two int
arguments to perform the calculation.
Example:
int function_name(int var1, int var2);

e) Function Return Type

Function return type tells what type of value is returned after all functions are executed.
When we don’t want to return a value, we can use the void data type.
Example:
int func (parameter_1,parameter_2);
The above function will return an integer value after running statements inside the function.
Note: Only one value can be returned from a C function. To return multiple values, we have
to use pointers or structures.

Conditions of Return Types and Arguments

In C programming language, functions can be called either with or without arguments and
might return values. They may or might not return values to the calling functions.

1. Function with no arguments and no return value

2. Function with no arguments and with return value

3. Function with argument and with no return value

4. Function with arguments and with return value

How Does C Function Work?

Working of the C function can be broken into the following steps as mentioned below:

1. Declaring a function: Declaring a function is a step where we declare a function.


Here we define the return types and parameters of the function.

2. Defining a function:

3. Calling the function: Calling the function is a step where we call the function by
passing the arguments in the function.

4. Executing the function: Executing the function is a step where we can run all
the statements inside the function to get the final result.

5. Returning a value: Returning a value is the step where the calculated value after
the execution of the function is returned. Exiting the function is the final step
where all the allocated memory to the variables, functions, etc is destroyed
before giving full control to the main function.

Program example:

// C program to show function


// call and definition
#include <stdio.h>

// Function that takes two parameters


// a and b as inputs and returns
// their sum

int sum(int a, int b){return a + b;}

// Driver code

int main()
{

// Calling sum function and


// storing its value in add variable

int add = sum(10, 30);


printf("Sum is: %d", add);
return 0;
}

Output

Sum is: 40

As we noticed, we have not used explicit function declaration. We


simply defined and called the function.

e) Types of Functions

There are two types of functions in C:

● Library Functions
● User Defined Functions
Library Function

A library function is also referred to as a “built-in function”. A compiler package already exists
that contains these functions, each of which has a specific meaning and is included in the
package. Built-in functions have the advantage of being directly usable without being
defined, whereas user-defined functions must be declared and defined before being used.

#include <math.h> // this is a header file . it has the predefined


math functions that will be used

#include <stdio.h>// this is another header file. The printf()


function is defined in this file.

// Driver code

int main() {
double Number;
Number = 49;

// Computing the square root with


// the help of predefined C
// library function

double squareRoot = sqrt(Number);


printf("The Square root of %.2lf = %.2lf", Number, squareRoot);
return 0;
}

For Example:
pow(), sqrt(), strcmp(), strcpy() etc.

User Defined Function

Functions that the programmer creates are known as User-Defined functions or “tailor-
made functions”. User-defined functions can be improved and modified according to the
need of the programmer.

Example:
// C program to show
// user-defined functions

#include <stdio.h>

int sum(int a, int b){ return a + b; }

// Driver code

int main(){
int a = 30, b = 40;

// function call

int res = sum(a, b);


printf("Sum is: %d", res);
return 0; }

2) Loops

Loops in programming are used to repeat a block of code until the specified condition is met.
A loop statement allows programmers to execute a statement or group of statements
multiple times without repetition of code.

for(int i = 0; i < n; ++i){ printf("Body of for loop which will


execute till n");}

● Initialization Expression: In this expression, we assign a loop variable or loop


counter to some value. for example: int i=0;

● Test Expression: In this expression, test conditions are performed. If the condition
evaluates to true then the loop body will be executed and then an update of the loop
variable is done. If the test expression becomes false then the control will exit from
the loop. for example, i<=9;

● Update Expression: After execution of the loop body loop variable is updated by
some value it could be incremented, decremented, multiplied, or divided by any
value.

C program to illustrate the need of loops.

The first program shows how you must proceed to print text several times. You’d need to
write as many printf() functions as you need to have the text printed the times you want .
#include <stdio.h>

int main(){
printf( "Hello World\n");
printf( "Hello World\n");
printf( "Hello World\n");
printf( "Hello World\n");
printf( "Hello World\n");
return 0;
}

Loops simplify this process, saving you all that typing.

// C program to illustrate for loop

#include <stdio.h>

// Driver code

int main(){
int i = 0;
for (i = 1; i <= 10; i++){ printf( "Hello World\n");};
return 0; };

1.2 Data structures


A data structure is a specialized format for organizing, processing, retrieving and storing
data.
You’ll find through this chapter program examples with some code that wasn't yet explained.
I’ll give a quick introduction so you can grasp the content better until they’re discussed more
deeply in their corresponding chapters.

1) Array Data Structure

An array in C is a fixed-size collection of similar data items stored in contiguous memory


locations. It can be used to store the collection of primitive data types such as int, char, float,
etc., and also derived and user-defined data types such as pointers, structures, etc.
a) C Array Declaration

In C, we have to declare the array like any other variable before using it. We can declare an
array by specifying its name, the type of its elements, and the size of its dimensions. When
we declare an array in C, the compiler allocates the memory block of the specified size to
the array name.

Syntax of Array Declaration

data_type array_name [size];


or
data_type array_name [size1] [size2]...[sizeN];

where N is the number of dimensions.

Program description :

// C Program to illustrate the array declaration


#include <stdio.h>

int main()
{

// declaring array of integers


int arr_int[5];
// declaring array of characters
char arr_char[5];

return 0;
}
b) C Array Initialization

Initialization in C is the process to assign some initial value to the variable. When the
array is declared or allocated memory, the elements of the array contain some
garbage value. So, we need to initialize the array to some meaningful value. There
are multiple ways in which we can initialize an array in C.

● Array Initialization with Declaration

In this method, we initialize the array along with its declaration. We use an initializer
list to initialize multiple elements of the array. An initializer list is the list of values
enclosed within braces { } separated by comma.

data_type array_name [size] = {value1, value2, ...


valueN};

● Array Initialization without Size Declaration

If we initialize an array using an initializer list, we can skip declaring the size of the
array as the compiler can automatically deduce the size of the array in these cases.
The size of the array in these cases is equal to the number of elements present in the
initializer list as the compiler can automatically deduce the size of the array.

data_type array_name[] = {1,2,3,4,5};

The size of the above arrays is 5 which is automatically


deduced by the compiler.

● Array Initialization after Declaration (Using Loops)

We initialize the array after the declaration by assigning the initial value to each
element individually. We can use for loop, while loop, or do-while loop to assign the
value to each element of the array.
for (int i = 0; i < N; i++) {
array_name[i] = value i;
}

Program Description:

Example of Array Initialization in C

// C Program to demonstrate array initialization


#include <stdio.h>

int main()
{
// array initialization using initialier list

int arr[5] = { 10, 20, 30, 40, 50 };

// array initialization using initializer list without


// specifying size

int arr1[] = { 1, 2, 3, 4, 5 };

// array initialization using for loop

float arr2[5];
for (int i = 0; i < 5; i++) {
arr2[i] = (float)i * 2.1; }
return 0;
}

d) Access Array Elements

We can access any element of an array in C using the array subscript operator [ ]
and the index value i of the element.

array_name [index];

One thing to note is that the indexing in the array always starts with 0, i.e., the first
element is at index 0 and the last element is at N – 1 where N is the number of
elements in the array.
Program Description :

// C Program to illustrate element access using array

#include <stdio.h>

int main()
{

// array declaration and initialization


int arr[5] = { 15, 25, 35, 45, 55 };

// accessing element at index 2 i.e 3rd element


printf("Element at arr[2]: %d\n", arr[2]);

// accessing element at index 4 i.e last element


printf("Element at arr[4]: %d\n", arr[4]);

// accessing element at index 0 i.e first element


printf("Element at arr[0]: %d", arr[0]);

return 0;
}

Output
Element at arr[2]: 35
Element at arr[4]: 55
Element at arr[0]: 15

e) Update Array Element


We can update the value of an element at the given index i in a similar way to
accessing an element by using the array subscript operator [ ] and assignment
operator =.

array_name[i] = new_value;

f) Length of Array in C

It can be determined by using the different methods mentioned below:

● Using sizeof() Operator

● Using Pointer Arithmetic

● Using Loop

Using sizeof() Operator

The sizeof operator is a compile-time unary operator that calculates the size of the variables
and datatypes. It returns an integer value that represents the size of the expression or a
variable in bytes. The sizeof operator is primarily used for dynamic memory allocation but it
can also be used to find the length of an array.
The trick is to first find the size of the whole array in bytes and the size of a single element
using the sizeof operator and then divide the size of the whole array by the size of a single
element so that we can get the number of elements in the array.

Syntax:
data_type size = sizeof(Array_name) / sizeof(Array_name[index]);
In the above syntax,

● data_type: It is the type of variable in which we want to store the length of the
array.(like int, size_t, etc.).

● Array_name: It is the name of the array you want to find the size of.

● sizeof(Array_name): It is an operator that returns the size of the entire array in


bytes.

● sizeof(Array_name[index]): It returns the size of a single element in the array in


bytes.

● index: It is the index of any element in the array.


// C Program to calculate size of an array using sizeof()
// operator
#include <stdio.h>

int main()
{

int Arr[] = { 1, 2, 3, 4, 5 };

// variable to store size of Arr


int length = sizeof(Arr) / sizeof(Arr[0]);

printf("The length of the array is: %d\n", length);

return 0;
}

Output

The length of the array is: 5


Using Pointer Arithmetic

We can also calculate the length of an array in C using pointer arithmetic. This solution of
using a pointer is just a hack that is used to find the number of elements in an array.

Syntax:
data_type length = *(&arr + 1) - arr;

In the above syntax:

● &arr: Pointer to an array of elements.

● (&arr + 1): Address of memory ahead of the array as pointer


type is a pointer to an array of integers.

● *(&arr + 1) – arr: Inclusive difference between the start


and the end of the array

// C Program to calculate size of an array using pointer arithmetic


#include <stdio.h>
int main()
{

int Arr[] = { 1, 2, 3, 4, 5, 6 };
// variable to store the size of Arr
int length = *(&Arr + 1) - Arr;

printf( "Number of elements in Arr[] is: %d", length);


return 0;
}

Output

Number of elements in Arr[] is: 6

Using Loop

The loop method is used to calculate the length of an array in C. It iterates through all the
elements of an array and increments the count.
// C Program to calculate size of an array using loop
#include <stdio.h>

int arr_length(int arr[])


{
int i;
int count = 0;
for(i=0; arr[i]!='\0'; i++)
{
count++;
}
return count;
}

int main()
{
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int n;

n = arr_length(arr);
printf("Length of Array is: %d", n);

return 0;
}

Output
Length of Array is: 10

Note: Please noteThe iterative methods of finding the length of the strings (array of
characters) also cannot be applied to the array of other types as there is no end indicator in
these array types in contrast to the ‘\0’ NULL character marking the end of the string. that
these methods only works when the array is declared in the same scope. These methods
will fail if we try them on an array which is passed as a pointer. This happens due to Array
Decay

g) C Array Traversal

Traversal is the process in which we visit every element of the data structure. For C array
traversal, we use loops to iterate through each element of the array.

Array Traversal using for Loop

for (int i = 0; i < N; i++) {


array_name[i];
}

Program Description:

// C Program to demonstrate the use of array


#include <stdio.h>

int main()
{
// array declaration and initialization
int arr[5] = { 10, 20, 30, 40, 50 };

// modifying element at index 2


arr[2] = 100;

// traversing array using for loop


printf("Elements in Array: ");
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}

return 0;
}

Output

Elements in Array: 10 20 100 40 50

h) Types of Array in C

There are two types of arrays based on the number of dimensions it has. They are as
follows:

● One Dimensional Arrays (1D Array)


● Multidimensional Arrays

One Dimensional Array in C

The One-dimensional arrays, also known as 1-D arrays in C are those arrays that
have only one dimension.

Syntax of 1D Array in C:

array_name [size];

Program Description:

// C Program to illustrate the use of 1D array


#include <stdio.h>
int main()
{

// 1d array declaration
int arr[5];

// 1d array initialization using for loop


for (int i = 0; i < 5; i++) {
arr[i] = i * i - 2 * i + 1;
}

printf("Elements of Array: ");


// printing 1d array by traversing using for loop
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}

return 0;
}

output

Elements of Array: 1 0 1 4 9

Multidimensional Array in C

Multi-dimensional Arrays in C are those arrays that have more than one dimension.
Some of the popular multidimensional arrays are 2D arrays and 3D arrays. We can
declare arrays with more dimensions than 3d arrays but they are avoided as they get
very complex and occupy a large amount of space.

● Two-Dimensional Array in C

A Two-Dimensional array or 2D array in C is an array that has exactly two


dimensions. They can be visualized in the form of rows and columns organized in a
two-dimensional plane.

Syntax of 2D Array in C
array_name[size1] [size2];

Here,

size1: Size of the first dimension.


size2: Size of the second dimension.
Program description:

// C Program to illustrate 2d array


#include <stdio.h>

int main()
{

// declaring and initializing 2d array


int arr[2][3] = { 10, 20, 30, 40, 50, 60 };

printf("2D Array:\n");
// printing 2d array
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ",arr[i][j]);
}
printf("\n");
}

return 0;
}

Output
2D Array:
10 20 30
40 50 60

● Three-Dimensional Array in C
Another popular form of a multi-dimensional array is Three Dimensional Array or 3D
Array. A 3D array has exactly three dimensions. It can be visualized as a collection of
2D arrays stacked on top of each other to create the third dimension.

Syntax of 3D Array in C:

array_name [size1] [size2] [size3];

Program Description :

// C Program to illustrate the 3d array


#include <stdio.h>

int main()
{

// 3D array declaration
int arr[2][2][2] = { 10, 20, 30, 40, 50, 60 };

// printing elements
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
printf("%d ", arr[i][j][k]);
}
printf("\n");
}
printf("\n \n");
}
return 0;
}
Output
10 20
30 40
50 60
0 0

chapter

1. STRINGS

A String in C programming is a sequence of characters terminated with a null character ‘\0’.


The C String is stored as an array of characters. The difference between a character array
and a C string is that the string is terminated with a unique character ‘\0’.

a) C String Declaration Syntax

Declaring a string in C is as simple as declaring a one-dimensional array. Below is the basic


syntax for declaring a string.
char string_name[size];
In the above syntax str_name is any name given to the string variable and size is used to
define the length of the string, i.e the number of characters strings will store.
There is an extra terminating character which is the Null character (‘\0’) used to indicate
the termination of a string that differs strings from normal character arrays.

b) Ways to Initialize a String in C

We can initialize a C string in 4 different ways which are as follows:

● Assigning a string literal without size

String literals can be assigned without size. Here, the name of the string str acts as a pointer
because it is an array.
char str[] = "learning";
● Assigning a string literal with a predefined size

String literals can be assigned with a predefined size. But we should always account for one
extra space which will be assigned to the null character. If we want to store a string of size n
then we should always declare a string with a size equal to or greater than n+1.
char str[50] = "learning ";

● Assigning character by character with size

We can also assign a string character by character. But we should remember to set the end
character as ‘\0’ which is a null character.

char str[9] = { 'L','e','a','r','n','i','n','g','\0'};

● Assigning character by character without size

We can assign character by character without size with the NULL character at the end. The
size of the string is determined by the compiler automatically.
char str[] = { 'L','e','a','r','n','i','n','g','\0'};
Note: When a Sequence of characters enclosed in the double quotation marks is
encountered by the compiler, a null character ‘\0’ is appended at the end of the string by
default.

Note: After declaration, if we want to assign some other text to the string, we have to
assign it one by one or use built-in strcpy() function because the direct assignment of
string literal to character array is only possible in declaration.

Program description:

// C program to illustrate strings

#include <stdio.h>
#include <string.h>
int main()
{
// declare and initialize string
char str[] = "learning";

// print string
printf("%s\n", str);

int length = 0;
length = strlen(str);

// displaying the length of string


printf("Length of string str is %d", length);

return 0;
}

Output

learning
Length of string str is 5

We can see in the above program that strings can be printed using normal printf statements
just like we print any other variable. Unlike arrays, we do not need to print a string, character
by character.
Note: The C language does not provide an inbuilt data type for strings but it has an access
specifier “%s” which can be used to print and read strings directly.

1.1 USER INPUT

The following example demonstrates how to take string input using scanf() function in C

// C program to read string from user


#include<stdio.h>

int main()
{
// declaring string
char str[50];

// reading string
scanf("%s",str);
// print string
printf("%s",str);

return 0;
}

Input
learning
Output
learning

You can see in the above program that the string can also be read using a single scanf
statement. Also, you might be wondering why we have not used the ‘&’ sign with the string
name ‘str’ in scanf statement! To understand this you will have to recall your knowledge of
scanf.
We know that the ‘&’ sign is used to provide the address of the variable to the scanf()
function to store the value read in memory. As str[] is a character array so using str without
braces ‘[‘ and ‘]’ will give the base address of this string. That’s why we have not used ‘&’ in
this case as we are already providing the base address of the string to scanf.

Now consider one more example:

// C Program to take input string which is separated by


// whitespaces

#include <stdio.h>

// driver code
int main()
{

char str[20];

// taking input string

scanf("%s", str);
// printing the read string

printf("%s", str);

return 0;
}

Input
Learning takes time and effort and much more than just going for a job.
Output
Learning takes time and effort and much more than just going for a job.

1.2 How to Read a String Separated by Whitespaces in C?


We can use multiple methods to read a string separated by spaces in C. The two of the
common ones are:

1. We can use the fgets() function to read a line of string and gets() to read characters
from the standard input (stdin) and store them as a C string until a newline character
or the End-of-file (EOF) is reached.

2. We can also scanset characters inside the scanf() function.

Example 1:

// C program to illustrate
// fgets()

#include <stdio.h>
#define MAX 50
int main()
{
char str[MAX];

// MAX Size if 50 defined


fgets(str, MAX, stdin);

printf("String is: \n");

// Displaying Strings using Puts


puts(str);
return 0;
}

Input
just type what you want
Output
String is:
just type what you want

Example 2 :

// c program
// scanset characters

#include <stdio.h>

// driver code
int main()
{
char str[20];

// using scanset in scanf

scanf("%[^\n]s", str);

// printing read string


printf("%s", str);

return 0;
}

Input
doing some more printing
Output
doing some more printing

Example 3 :

// C Program to illustrate strings


#include <stdio.h>

int main()
{

// creating array of character


char arr[6] = { 'h', 'e', 'y', '\0' };

// printing string
int i = 0;
while (arr[i]) {
printf("%c", arr[i++]);
}
return 0;
}

output : hey

1.3 Relationship between Arrays and Pointers

a ) Arrays and Pointers

The name of the array is a pointer to the array itself. The array name points to the first item.
The following sections discuss arrays and pointers.
Just in case you don't know you can use the following syntax to get the address of any data
structure:

Syntax: &variable_name

Example : double decNumber=10


std::cout<<&decNumber<< endl;

Output: 0x7ffc855092b0

Now let’s go all over the following program :

1. There’s an array variable declaration

2. There are three print statements using the array’s variable.


Snippet:

#include<iostream>

using namespace std;

int main(){

int arr[5]{1,2,3,4,5};

std::cout<<arr <<endl; // printing arr variable


std::cout<<&arr<< endl; // printing arr’s address variable
std::cout<<&arr[0]; // printing arr’s 0 index address

};

Each of the following statements will print the same address.that’s why it is said that an array
works similar to pointers.

a) std::cout<<arr <<std::endl; // printing arr variable


b) std::cout<<&arr<<std::endl; // printing arr’s address
variable
c) std::cout<<&arr[0]<<std::endl; // printing arr’s 0 index
address

Output:

a) arr: 0x7ffe359cf1d1
b) &arr: 0x7ffe359cf1d1
c) &arr[0]: 0x7ffe359cf1d1

From the sample it can be inferred that an array is a pointer


that holds the address of its first element.

b) Comparison between Pointers and Arrays:


In this case, both ptr and arr are pointers to the array element arr[0].

int *ptr = arr;

d) To Access Addresses

a) arr + 1 // access the address of the second element

b) &arr[1] // access the address of the second element

c) ptr + 1 // access the address of the second element

e) To Access Stored Values:

a) arr[1] // access the value of the address arr[1]

b) *(arr + 1) // access the value of the address arr[1]

c) ptr[1] // access the value of the address arr[1]

d) *(ptr + 1) // access the value of the address arr[1]

At first it might seem surprising that you can use the array notation ptr[i] for pointers.
The compiler translates arr[i] to *(arr + i)—in other words: “Start at address
arr, move i objects up, and access the object!” This also applies to ptr[i].

f) Arithmetic With Arrays and Pointers


Arrays and Pointers are closely related to each other such that we can use pointers to
perform all the possible operations of the array. The array name is a constant pointer to the
first element of the array and the array decays to the pointers when passed to the function.

Program Description:

// C Program to demonstrate the relation between arrays and


// pointers

#include <stdio.h>

int main()
{

int arr[5] = { 10, 20, 30, 40, 50 };


int* ptr = &arr[0];

// comparing address of first element and address stored


// inside array name

printf("Address Stored in Array name: %p\nAddress of "


"1st Array Element: %p\n",
arr, &arr[0]);

// printing array elements using pointers


printf("Array elements using pointer: ");
for (int i = 0; i < 5; i++) {
printf("%d ", *ptr++);
}
return 0;
}

output :

Address Stored in Array name: 0x7ffce72c2660


Address of 1st Array Element: 0x7ffce72c2660
Array elements using pointer: 10 20 30 40 50

g) String Arrays and Pointers

In C programming String is a 1-D array of characters and is defined as an array of


characters. But an array of strings in C is a two-dimensional array of character types. Each
String is terminated with a null character (\0). It is an application of a 2d array.

Syntax:
char variable_name[r] = {list of string};
Here,

● var_name is the name of the variable in C.

● r is the maximum number of string values that can be stored in a string array.

● c is the maximum number of character values that can be stored in each string
array.

// C Program to print Array


// of strings

#include <stdio.h>
// Driver code
int main()
{
char arr[3][10] = {"hey","you ", "laugh more "};
printf("String array Elements are:\n");

for (int i = 0; i < 3; i++)


{
printf("%s\n", arr[i]);
}
return 0;
}

Output

String array Elements are:

hey
you
laugh more

We have 3 rows and 10 columns specified in our Array of String but because of pre-
specifying the size of the array of strings the space consumption is high. So, to avoid high
space consumption in our program we can use an Array of Pointers in C.

h) Invalid Operations in Arrays of Strings

We can’t directly change or assign the values to an array of strings in C.

Example:
char arr[3][10] = {"Geek", "Geeks", "Geekfor"};
Here, arr[0] = “GFG”; // This will give an Error that says
assignment to expression with an array type.

To change values we can use strcpy() function in C


strcpy(arr[0],"GFG"); // This will copy the value to the arr[0].

i) Array of Pointers of Strings

In C we can use an Array of pointers. Instead of having a 2-Dimensional character array, we


can have a single-dimensional array of Pointers. Here pointer to the first character of the
string literal is stored.
Syntax:
char *arr[] = { "Geek", "Geeks", "Geekfor" };

// C Program to print Array


// of Pointers

#include <stdio.h>

// Driver code

int main()
{
char *arr[] = {"Geek", "Geeks", "Geekfor"};
printf("String array Elements are:\n");

for (int i = 0; i < 3; i++)


{
printf("%s\n", arr[i]);
}
return 0;
}

Output

String array Elements are:


Geek
Geeks
Geekfor

Chapter

1. Using variables with operators

When you initialize a variable you can start performing operations with it like additions,
subtraction and many more according to the data type you’re working with.
I’ll introduce operators and their use cases.
there’s a wide range of operators that will let you work along the program to achieve its
objectives.

Operators
1.1 Binary Operators

The figure below makes clear why they’re called binary operators because to perform a
calculation you need two operands

a) ARITHMETIC OPERATORS

The following table shows the binary arithmetic operators that can be used in your C
program.
A recommendation is to always use the same type to avoid program errors.

Example :

Program Description: calculate meters based on centimeters , add them and print the
values.

#include <stdio.h>

int main () {

float meters=3.65;
float centimeters=4.25;

float centimeterToMeters= centimeters/100;

printf("%f", centimeterToMeters);

float sum = centimeterToMeters +meters;

printf("%f",sum);

return 0;

b) ASSIGNMENT OPERATORS

Different types of assignment operators are shown below:

“=”: This is the simplest assignment operator. This operator is used to assign the value on
the right to the variable on the left.
Example:

a = 10;
b = 20;
ch = 'y';

“+=”: This operator is a combination of ‘+’ and ‘=’ operators. This operator first adds the
current value of the variable on left to the value on the right and then assigns the result to
the variable on the left.

Example:

If initially value stored in a is 5. Then (a += 6) = 11.

“=”This operator is a combination of ‘-‘ and ‘=’ operators. This operator first subtracts the
current value of the variable on the left from the value on the right and then assigns the
result to the variable on the left.

Example:

(a -= b) can be written as (a = a - b)
If initially value stored in a is 8. Then (a -= 6) = 2.

“*=”This operator is combination of ‘*’ and ‘=’ operators. This operator first multiplies the
current value of the variable on left to the value on the right and then assigns the result to
the variable on the left

Example:

(a *= b) can be written as (a = a * b)
If initially value stored in a is 5. Then (a *= 6) = 30.

“/=”This operator is a combination of ‘/’ and ‘=’ operators. This operator first divides the
current value of the variable on the left by the value on the right and then assigns the result
to the variable on the left.

Example:

(a /= b) can be written as (a = a / b)
If initially value stored in a is 6. Then (a /= 2) = 3.

Program Description :

// C program to demonstrate
// working of Assignment operators
#include <stdio.h>

int main()

// Assigning value 10 to a
// using "=" operator
int a = 10;
printf("Value of a is %d\n", a);

// Assigning value by adding 10 to a


// using "+=" operator
a += 10;
printf("Value of a is %d\n", a);

// Assigning value by subtracting 10 from a


// using "-=" operator
a -= 10;
printf("Value of a is %d\n", a);

// Assigning value by multiplying 10 to a


// using "*=" operator
a *= 10;
printf("Value of a is %d\n", a);

// Assigning value by dividing 10 from a


// using "/=" operator
a /= 10;
printf("Value of a is %d\n", a);

return 0;
}

c) COMPARISON OPERATORS

Relational operators commonly called comparison operators are used to perform


comparison binary operations (you also need two operands) . they always return a boolean
value when evaluating the expressions . So they evaluate to true or false once the task is
finished.
you’ll see them most commonly used in action when writing conditionals ( it’ll be explained
in the next chapter)
Take a look at the table below and their use cases .

This table shows some examples :

Program Description : comparing if 5 is greater than 6.

#include <stdio.h>

int main () {
_Bool comparisonResult= 5>6;

printf("%\n", comparisonResult); // prints 0 which that means false

return 0;
}

d) LOGICAL OPERATORS

Logical operators comprise the boolean operators && (AND), || (OR), and ! (NOT).
They can be used to create compound conditions and perform conditional execution of a
program depending on multiple conditions.
A logical expression results in a value false or true, depending on whether the logical
expression is correct or incorrect, just like a relational expression.

In other words it takes two expressions . An expression can be defined as any code that
gets executed and ends up being a Value.

Example :

int sum = 2 + 2 ; // it ends up being a value assigned to the sum


variable

The following table shows variable A and B , their possible boolean values and compares
them using logical operators showing the returned boolean value.
● && And Operator

The and operator && evaluates an expression and returns a boolean value (true or false) .
it will return true only if both operands are true, so the logical expression:

check the following program:


#include <stdio.h>

int main () {
int x=2;
int y=3;

// it’s going to return true if both expressions are true


// two compared expressions that returns a value (true)

_Bool result =(x>0 && y==3)

// returns 1 (true)

printf(“%d”,result);}

● The OR operator ||
will return true only if at least one operand is true, so the value
of the expression

#include <stdio.h>

int main () {
int x=2;
int y=4;

_Bool result= ( x>0 || y==3);

// just because X is bigger than 0 . The expression comparison


returns true

printf(“%d”,result);

return 0;

}
● The NOT operator !

will return true only if its operand is false. If the variable flag
contains the value false (or the value 0), !flag returns the boolean value true.

Program Description: Not !operator example use.

// A remainder any value that does not equal 0 . When used along the Not! operator will
return 1. The Value 0 represents False when it comes to Boolean types and 1 represents
True.
Now comes the trick , any values exceeding 0 will be treated as truthy values .
when you apply this operator it returns the opposite boolean value.
Let's check this down below.

#include <stdio.h>

int main (){

int x=0; // this is considered a falsy value


int z=3;//this is considered a truthy value

printf(“%d”,!x ); // when applied it returns 1 that is the opposite

printf(“%d”,!x ); // when applied it returns 0. all values above 0


are considered truthy after the expression get evaluated it returns
0.

return 0;

};
1.3 Unary Arithmetic Operators

They require one operand to perform an operation.

Program description: increment and decrement variables

#include <stdio.h>

int main () {

int num=1;

// increment operator . adds 1 to num


num++;
printf("%d\n", num);

// adds 1 to num
num ++;
printf("%d\n",num);

// decrement operator. Subtracts 1 to num

num--;

printf("%d\n", num);

// subtracts one to num

num--;

printf("%d\n",num);
return 0;

};

Chapter 4

1. Conditionals / Control Flow Statements

A control flow statement is a statement that results in a choice being made as to which of two or
more paths to follow.

1.1 If Statements

if-statements are used to diagram the flow execution of a program


according to a certain condition.
you might have noticed that a program execution starts in the main
function from the first line of code until it reaches the return
statement.
if-statements let you execute a piece of code or skip its execution
depending on whether the expression provided in the condition
results or ends up being true or false .

here’s a snip syntax :


if (condition) {
// block of code to be executed if the condition is true
}

Program Description : compares two numbers and if the expression results in numOne
being smaller than numTwo the printf() function executes that is the program executes the
code between the braces if not the program skips the code and just ends without any
further execution.

#include <stdio.h>

int main () {

int numOne=2;
int numTwo=5;

if (numOne<numTwo){

printf(“numTwo is greater than numOne”)

}
return 0;

};

output

numTwo is greater than numOne

1.2 If-Else Statements


if (condition) {
// block of code to be executed if the condition is true
} else {
// block of code to be executed if the condition is false
}

Program Description : it is the same case as before but the program now executes the
code block in the else statement if the condition is not satisfied.
I changed the numOne value to 5 when the if expression gets evaluated it evaluates to false
but this isn't going to stop the program . in this case the else printf() executes before
reaching the return statement.

#include <stdio.h>

int main () {

int numOne=5;
int numTwo=5;

if (numOne<numTwo){

printf(“numTwo is greater than numOne”);

} else {

printf(“numOne is greater than numTwo”);

};
return 0;

};

1.3 If-else-if statements

Imagine that you want to evaluate several conditions. To accomplish this you’d need
to make use of several if /else-if statements . when one expression returns true the block
stops executing. if more than one condition is satisfied the one reached first executes and
the rest is not evaluated.

Structogram else-if chain syntax


if (condition 1) {
statement 1

} else if (condition 2) {

statement 2

}else{

statement 3

};

An alternative way is to sequence several if keywords, as follows:

if (condition 1) {
statement 1
}

if (condition 2) {
statement 2
}

if (condition 3) {
statement 3
}

Program Description : If- else-if statement used.

// C program to illustrate nested-if statement

#include <stdio.h>

int main()
{
int i = 20;

if (i == 10)
printf("i is 10");
else if (i == 15)
printf("i is 15");
else if (i == 20)
printf("i is 20");
else
printf("i is not present");

return 0;
}

1.4 Selection Statement – switch

The expression gets evaluated and executes the code that matches the case.
The break keyword prevents further execution.
if there’s no matching case the default case gets executed when included in the statement.
switch (expression)
{

case constant 1:
group-of-statements-1;
break;

case constant 2:
group-of-statements-2;
break;
...
default:
default-group-of-statements;
break;
}

Switch program example :

//C Program to illustrate the use of switch statement

#include <stdio.h>

int main()
{
// variable to be used in switch statement
int var = 2;
// declaring switch cases
switch (var) {
case 1:
printf("Case 1 is executed");
break;
case 2:
printf("Case 2 is executed");
break;
default:
printf("Default Case is executed");
break;
}

return 0;
}

1.5 Ternary Operator

It is kind of similar to the if-else statement as it follows the same algorithm as the if-else
statement but the conditional operator takes less space and helps to write the if-else
statements in the shortest way possible. It is also known as the ternary operator in C as it
operates on three operands

The conditional operator can be in the form:

variable = Expression1 ? Expression2 : Expression3;

Or the syntax can also be in this form:

variable = (condition) ? Expression2 : Expression3;

Or syntax can also be in this form:


(condition) ? (variable = Expression2) : (variable = Expression3);

The working of the conditional operator in C is as follows:

Step 1: Expression1 is the condition to be evaluated.


Step 2A: If the condition(Expression1) is True then Expression2 will
be executed.
Step 2B: If the condition(Expression1) is false then Expression3
will be executed.
Step 3: Results will be returned.

Example program

Description:

// C program to find largest among two


// numbers using ternary operator

#include <stdio.h>

int main()
{
int m = 5, n = 4;

(m > n) ? printf("m is greater than n that is %d > %d",


m, n)
: printf("n is greater than m that is %d > %d",
n, m);

return 0;
}

CHAPTER 5

1. LOOPS

Loops in programming are used to repeat a block of code until the specified condition is met.
A loop statement allows programmers to execute a statement or group of statements
multiple times without repetition of code.
1.1. For Loops

is a repetition control structure that allows programmers to write a loop that will be executed
a specific number of times. for loop enables programmers to perform n number of steps
together in a single line.

for (initialization; condition; increase){

statement1;

statement2;
...
statementN;
}

#include <stdio.h>
int main () {

for (int i = 0; i < 5; i++) {


printf(“%d”,i); };

return 0;

};

The example above can be splitted in three :

a) int i = 0 // it’s a variable declaration.


b) i < 5 // it’s the condition during which the statements
in the loop will be executed.
c) i++ // as long as the condition is true the i variable will
be incremented by one

the output of the following code will be : 4

Iteration Statement – while loop

Another iteration statement is the while loop. It is simpler than the for loop. it will execute the
code as long as the condition evaluates to true (expression is true).

Program description : C program to demonstrate while loop


#include <stdio.h>

int main()
{
// Initialization of loop variable
int i = 0;

// setting test expression as (i < 5), means the loop


// will execute till i is less than 5
while (i < 5) {

// loop statements
printf("GeeksforGeeks\n");

// updating the loop variable


i++;
}

return 0;
}

1.2 Iteration Statement – do-while loop

A Similar loop is to the do-while loop, where the condition is checked after the execution
of the body statements, instead of before.This means that the code gets executed at least
once. that's the main difference between the other loops , which won't run the code if the
condition isn’t met (it’s evaluated first)

Program Description: C Program to demonstrate the use of do...while loop


#include <stdio.h>

int main()
{

// loop variable declaration and initialization


int i = 0;
// do while loop
do {
printf("Geeks\n");
i++;
} while (i < 3);

return 0;
}

1.3 THE BREAK AND CONTINUE STATEMENTS

1.4 The continue statement in C


It is a jump statement that is used to bring the program control to the start of the loop. We
can use the continue statement in the while loop, for loop, or do..while loop to alter the
normal flow of the program execution. Unlike break, it cannot be used with a C switch case.

a) What is continue in C?

The C continue statement resets program control to the beginning of the loop when
encountered. As a result, the current iteration of the loop gets skipped and the control moves
on to the next iteration. Statements after the continue statement in the loop are not
executed.

b) Syntax of continue in C

The syntax of continue is just the continue keyword placed wherever we want in the loop
body.
continue;

c) Use of continue in C

The continue statement in C can be used in any kind of loop to skip the current iteration. In
C, we can use it in the following types of loops:

● Single Loops
● Nested Loops

Using continue in infinite loops is not useful as skipping the current iteration won’t make a
difference when the number of iterations is infinite.

The continue statement can be used in for loop, while loop, and do-while loop.

Program Example :

// C program to explain the use


// of continue statement with for loop

#include <stdio.h>

int main()
{
// for loop to print 1 to 8

for (int i = 1; i <= 8; i++) {

// when i = 4, the iteration will be skipped and for


// will not be printed

if (i == 4) {continue;}
printf("%d ", i); }

printf("\n");

int i = 0;

// while loop to print 1 to 8

while (i < 8) {

// when i = 4, the iteration will be skipped and for


// will not be printed

i++;
if (i == 4) {continue;}
printf("%d ", i);}

return 0;}

Output
1 2 3 5 6 7 8
1 2 3 5 6 7 8

d) How does it work ?

The working of the continue statement is as follows:

● STEP 1: The loop’s execution starts after the loop condition is evaluated to be
true.

● STEP 2: The condition of the continue statement will be evaluated.

● STEP 3A: If the condition is false, the normal execution will continue.

● STEP 3B: If the condition is true, the program control will jump to the start of the
loop and all the statements below the continue will be skipped.

● STEP 4: Steps 1 to 4 will be repeated till the end of the loop.

FLOWCHART OF CONTINUE IN C
1.5 The Break Statement

Use of break in C

The break statement in C is used for breaking out of the loop. We can use it with any type of
loop to bring the program control out of the loop. In C, we can use the break statement in the
following ways:

● Simple Loops

● Nested Loops

● Infinite Loops

● Switch case

Example 1:

//Break statements in C can be used with simple loops i.e, for loops, while loops, and
do-while loops.

// C Program to demonstrate break statement with for loop.

#include <stdio.h>

int main() {
// using break inside for loop to terminate after 2
// iteration

printf("break in for loop\n");


for (int i = 1; i < 5; i++) {
if (i == 3) {
break;
} else {
printf("%d ", i);}
};

// using break inside while loop to terminate after 2


// iteration

printf("\nbreak in while loop\n");

int i = 1;
while (i < 20) {
if (i == 3)
break;
else
printf("%d ", i);
i++;
}

return 0;
};

How does the break statement work ?


The working of the break statement in C is described below:

1. STEP 1: The loop execution starts after the test condition is evaluated.

2. STEP 2: If the break condition is present the condition will be evaluated.

3. STEP 3A: If the condition is true, the program control reaches the break
statement and skips the further execution of the loop by jumping to the
statements directly below the loop.

4. STEP 3B: If the condition is false, the normal flow of the program control
continues.
1.6 The Goto Statement

The C goto statement is a jump statement which is sometimes also referred to as an


unconditional jump statement. The goto statement can be used to jump from anywhere to
anywhere within a function.

Examples:

Type 1: In this case, we will see a situation similar to as shown in Syntax1 above. Suppose
we need to write a program where we need to check if a number is even or not and print
accordingly using the goto statement. The below program explains how to do this:
// C program to check if a number is
// even or not using goto statement

#include <stdio.h>

// function to check even or not


void checkEvenOrNot(int num)

{
if (num % 2 == 0)
// jump to even
goto even;
else
// jump to odd
goto odd;

even:
printf("%d is even", num);
// return if even
return;
odd:
printf("%d is odd", num);
}

int main()
{
int num = 26;
checkEvenOrNot(num);
return 0;
}

Output:
26 is even

Type 2: In this case, we will see a situation similar to as shown in Syntax2 above. Suppose
we need to write a program that prints numbers from 1 to 10 using the goto statement. The
below program explains how to do this.

// C program to print numbers


// from 1 to 10 using goto statement
#include <stdio.h>

// function to print numbers from 1 to 10


void printNumbers()
{
int n = 1;
label:
printf("%d ", n);
n++;
if (n <= 10)
goto label;
}

// Driver program to test above function


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

Disadvantages of Using goto Statement

● The use of the goto statement is highly discouraged as it makes the program
logic very complex.

● The use of goto makes tracing the flow of the program very difficult.

● The use of goto makes the task of analyzing and verifying the correctness of
programs (particularly those involving loops) very difficult.

● The use of goto can be simply avoided by using break and continue statements.

chapter 6

1.1 FUNCTIONS

A function consists in a piece of code that executes a set of instructions, performs a certain
operation and returns a value(optional ). If nothing is returned, the Void type is used.
1.2 Main Function

The main function is an integral part of the programming languages such as C. The main
function in C is where the execution of a program starts. It is a user-defined function that is
mandatory for the execution of a program because when a C program is executed, the
operating system starts executing the statements in the main() function.

a) Syntax of C main() Function

return_type main() {
// Statement 1;
// Statement 2;
// and so on..
return;
}
We can write the main function in many ways in C language as follows:

1. int main(){} or int main(void){}

2. main(){} or void main(){} or main(void){} or void


main(void){}

In the above notations, int means integer return type, and void return type means that does
not return any information, or (void) or () means that does not take any information.

b) Important Points about C main Function

● It is the function where the program’s execution starts.

● Every program has exactly one main function.

● The name of this function should be “main” not anything else.

● The main function always returns an integer value or void.

● The main function is called by OS, not the user.

c) Types of C main Functions

1. Main function with no arguments and void return type

2. Main function with no arguments and int return type


3. Main function with the Command Line Arguments

d) Main Function with No Arguments and Void Return Type

Let’s see the example of the main function inside which we have written a simple program
for printing a string. In the below code, first, we include a header file and then we define a
main function inside which we write a statement to print a string using printf() function. The
main function is called by the operating system itself and then executes all statements inside
this function.
Syntax :

void main()
{
// Function body
}

The above function is equivalent to:

void main (void)


{
// Function Body
}

Program Example :

// C Program to show main with no return type and no


// arguments

#include <stdio.h>

// Defining a main function


void main()
{

// code
printf("Hello Geek!");
}

Output

Hello Geek!
Note: The return type of main function according to C standard should be int only. Even if
your compiler is able to run void main(), it is recommended to avoid it.

e) Main Function with No Arguments and int Return Type

In this example, we use the int return type in the main() function that indicates the exit status
of the program. The exit status is a way for the program to communicate to the operating
system whether the program was executed successfully or not. The convention is that a
return value of 0 indicates that the program was completed successfully, while any other
value indicates that an error occurred.

Syntax

int main()
{
// Function body
}

or

int main(void)
{
// Function Body
}

Program example :

// C Program to show the main function with int return type


// and no arguments

#include <stdio.h>
int main()
{ printf("Hello Geek!");
return 0;}

Output
Hello Geek!

f) Main Function with the Command Line Arguments

In this example, we have passed some arguments in the main() function as seen in the
below code. These arguments are called command line arguments and these are given at
the time of executing a program.
The first argument argc means argument count which means it stores the number of
arguments passed in the command line and by default, its value is 1 when no argument is
passed.
The second argument is a char pointer array argv[] which stores all the command line
arguments passed. We can also see in the output when we run the program without passing
any command line argument the value of argc is 1.

Syntax

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


{
// Function body
}

Program example :

// C Program to illustrate the main function with command line


arguments

#include <stdio.h>

int main(int argc, char* argv)


{
// printing the count of arguments

printf("The value of argc is %d\n", argc);

// printing each argument

for (int i = 0; i < argc; i++) {


printf("%s \n", argv[i]);
}

return 0;
}

1.3 FUNCTION CREATION

User Defined Functions

I've previously detailed the creation process to put functions into work.
This chapter intends to dive deeper into their concept and application.

1) Declaration

a)int sum ( ); // no parameters declaration

b)int sum (int a, int b ) // declaration with parameters

2) Definition

a) int sum {
int num1 =2;
int num 2= 5;
int total = num1 + num2 ;
cout<< total;};

b) int sum (int a, int b){


int total = a +b;
cout<< total ;}

3) Calling :

a) sum ();
b) sum (1+2);

1) Function Declaration

In a function declaration, we must provide the function name, its return type, and the number
and type of its parameters. A function declaration tells the compiler that there is a function
with the given name defined somewhere else in the program.
Syntax: return_type - function_name - ( parameter list );

It’s composed of the returned value type, the function’s name and a list of parameters.
parameters can be optional but you must specify the type of each of them.
Function calling can be carried out with or without parameters.

a) Parameterized function creation

1. Just like when you declare a variable you state its type but in this case what you're
stating is its return type. if the result of the operation effectuated returns an integer
you must start the declaration with an Int type.

2. Next you decide which name the function will take according to the expected
operation which at the time of writing turns out to be a “sum“.

3. Last step is to insert into the parenthesis the type of variables it is going to take to
execute the defined set of instructions (statements) in the definition step when the
function is called.

Example: 1.int
2.sum
3.(int a , int b )

int sum (int x,int y);


b) Non-parameterized function creation

It takes no parameters but still executes the defined statements.

Example: 1.int 2.sum 3.( )

int sum ();

2) Function Definition

When we define a function, we need to make sure that the signature (the return
value, the name, and the parameters) are the same as the declaration.
You must always use the return keyword unless nothing is returned.
A function can return a value by using the return keyword, followed by the value it wants to
return. If there’s no value to return, the Void type is used.

a) Parameterized function definition

int sum (int a, int b ){


int result = a+ b;
return result;
}

b) Non-parameterized function definition

int sum ( ){
int a= 10;
int b=11;
int result = a+ b;
return result;
}

c) Using a Function Prototype

The C function prototype is a statement that tells the compiler about the function’s name, its
return type, numbers and data types of its parameters. By using this information, the
compiler cross-checks function parameters and their data type with function definition and
function call.
Function prototype works like a function declaration where it is necessary where the function
reference or call is present before the function definition but optional if the function definition
is present before the function call in the program.
Most programmers declare a function on top of the file and define it after the main function
with the objective of making the code more manageable , more organized and more
readable.

#include <iostream>
using namespace std;

// function declaration or function prototype

void PrintName(string first, string last);

// main function

int main() {

PrintName("Thomas", "Jefferson");
return 0;

// function definition

void PrintName(string first, string last){

string fullname = first + " " + last;


cout << fullname << endl;

Although the previous structure of the code is the most preferred you could also
declare and define a function at a different place like in a header file or in any different order
in the same file although some compilers might complain if you don't follow the previous
order .Nevertheless try to stick to the above model since it is the standard followed by most
c++ programmers.

Difference between Function Declaration and Function Prototype


e) A special kind of function. Inline Functions

C++ provides inline functions to reduce the function call overhead.


when the inline function is called, the whole code of the inline function gets inserted or
substituted at the point of the inline function call. This substitution is performed by the C++
compiler at compile time.

The compiler inserts the code of an inline function at the address where the function is
called and thus avoids jumping to a subroutine. The definition of an inline function is
introduced by the inline keyword in the function header.
An inline function must be defined in the source file in which it is called. You cannot
simply supply a prototype of the function. The code containing the instructions must
also be available to the compiler. It therefore makes sense to define inline functions in
header files, in contrast to “normal” functions. This means the function will be available
in several source files.
3) Function Calling

To call a function means that the code statements are going to be executed .
Basically the steps when dealing with function calling are as follows:
a) CALLING METHODS:

● Function Call without parameters

This is going to print “hello" on the console.

// DECLARATION

string sayHello();

// DEFINITION

string sayHello(){
string hello = “hello”;
std::cout<< hello <<std::endl; };

// FUNCTION CALL

sayHello();

● Function call with parameters

To call a function that takes parameters, you need to write the name of the function,
followed by a list of expressions inside a pair of parentheses. Calling a function means that
it's going to execute the code defined in it.

Syntax : function_name( arguments) ;


sum (1,2);

output: 3

NOTE

● A parameter is a variable that was defined by a function, and can be used to


provide data as per the code:

// int x and int y are the parameters of the sum function.

int sum (int x,int y);

● An argument is the value the caller wants to bind to the parameters of the function.

// number 1 and number 2 are the arguments you provide to the


parameterized function sum

sum (1,2);

When you call the function you are giving it these two numbers as arguments. so arguments
are the actual value you assign to the defined parameters .

Parameters can be variables of any data type :

integer, double ,float , char , string , wchat_t, boolean , pointer,


reference, objects ,arrays and you can even take a whole function.

Example:

int a , b = 2;

int sum (int num1, int num2){


int result = num1+ num2
return result;
}

sum (a,b);

Output: 4

1.4 Function Overloading


This means that you can define two functions with the same identifier(name) as long as their
parameters and return types are different .
Depending on the arguments you assign when you call a function the compiler will execute
the one that matches them.

#include <iostream>
using namespace std;
void Combine(string first, string second)
{
cout << first << " " << second << endl;
}
void Combine(int first, int second)
{
int sum = first + second;

cout << first << " " << second << " " << sum << endl;
}
int main()
{
Combine("David","Letterman");
Combine(15,20);
return 0;}

1.5 Parameter types

1) Default Parameters

2) Passed by Value

3) Passed by Reference

1) DEFAULT PARAMETERS

A function can be defined to take Default Parameters. See the example below:

int multiply(int multiplied, int multiplier = 1);

The caller of the function can call multiply either with 1 or 2 arguments:

multiply(10); // Returns 10

multiply(10, 2); // Returns 20


Note

PASSING BY VALUE VS BY REFERENCE

The first term, passing by value, means sending the actual value of a variable to a function
when you call it. When working with C++, you accomplish this
task by calling the function with the variable. The second term,
passing by reference, means sending the address of the variable to the function so that
the function can modify the original content of that variable.

2) AS A VALUE TYPE

When the parameter is a value type, we say that the function is taking
an argument by value or the argument is passed by value.
In this case ,arguments are copied and a new local object is created each time the function
is called.

int sum (int a , int b){


int total = a +b;
return total ;};

int main () {
int a =10;
int b=11;
sum(a,b);
return 0;};

Output: 21

a) Returning by Value

A function whose return type is a value type is said to return by value.


When a function that returns by value reaches a return statement, the program
creates a new object, which is initialized from the value of the expression in the return
statement.
This object is called temporary because its lifetime is valid only while the full expression
in which it is created is executed.

The calling code can then use the returned temporary value in another expression or
assign it to a value.

#include <iostream>
using namespace std

int multiplication (int x,int y);

int main() {
int x = 3;
int y=5;
int result;
result=multiplication(x,y);
return 0;
}

int multiplication (int x,int y){


int total= x * y;
return total;
}

In this case the sum function returned value gets stored in the result variable.

b) Passing by const Value

In this program you are passing two const variables to the function multiplication in order to
multiply them.
If you try to change the value of any of the passed arguments you'll get an increment of read
only parameter error.

#include <iostream>

using namespace std;

int multiplication (const int x, const int y);

int main() {

// notice the following , here below x and y are defined as const


but you could also define them as int. this won’t alter the
constness of the parameters defined in the function. when you pass
by value you get a copy of the value of the original variable
you’re passing as argument.
therefrom a new const variable will be created by the function and
it’ll exist until it reaches its final execution statement or return
statement .

const int x = 3;
const int y=5;
int result=multiplication(x,y);
std::cout<< result<<std::endl; }

int multiplication (const int x, const int y){


x=10; // error
x++ //error

// this is totally fine you are not modifying either variable


you’re using them as an expression to return and store a value in
the Total variable.

int total= x * y;

return total;}

c) Returning By Const Value

There is no widespread reason to return by const value since the calling code often
assigns the value to a variable, in which case the const-ness of the variables is going
to be the deciding factor, or passes the value to a next expression, and it is rare for an
expression to expect a const value.

#include <iostream>
using namespace std;

const int multiplication (const int x, const int y);

int main() {
const int x = 3;
const int y=5;
const int result=multiplication(x,y);//
std::cout<< result<<std::endl;
return 0;
}

const int multiplication (const int x, const int y){


const int total= x * y;
return total;
}
3) REFERENCING

Referencing is achieved by the use of pointers.

Syntax: type * pointer = &variable_name;

Example 1:

int pencils = 3 ;
int *refToPencils = &pencils; // its value is now
pencil’s address

Program Example :

#include <cstdio>

int main() {

int original = 100;


int* ptr_original= &original;

// printing
printf("Original: %p\n", original);
printf("Reference: %p\n", ptr_original);

int new_value = 200;


ptr_original= new_value;

// printing
printf("Original: %p\n", original);
printf("New Value: %p\n", new_value);
printf("Reference: %p\n", ptr_original);

Original: 100
Reference: 100
Original: 200
New Value: 200
Reference: 200

This program initializes an int called original to 100. Then it declares a


reference to original called original_ref. From this point on, original_ref will
always refer to original. This is illustrated by printing the value of original
and the value referred to by ptr_original. They’re the same.
Next, you initialize another int called new_value to 200 and assign original
to it . Read that carefully: this assignment doesn’t reseat original_ref so
that it points to new_value. Rather, it assigns the value of new_value to the object
it points to (original).
The upshot is that all of these variables—original, ptr_original, and
new_value—evaluate to 200

a) Const References :

References to const cannot be used to change the object they refer to.
they’re read-only references.

a)const type variable_name;

b)const type *pointer_name = &variable_name;

Trying to modify the variable countries through refCountries throws a compiler error.

const int countries =250;

const int *ptrToCountries= &countries;

ptrToCountries++ // increment of a read-only references plus


the fact that the var countries is also const so there’s no
way to make any changes.

b) CONST REFERENCE TO A NON-CONSTANT VARIABLE :

You can modify the value of var countries but not from the refToCountries variable.
If you change the value of countries the changes will be visible in refToCountries ;

Syntax;

a) type variable_name;

b) const type *reference_name = &variable_name;

Snippet :
int countries =250;

const *ptrToCountries= countries;

ptrToCountries++ ;

Output:

// error increment of read-only variable reference

c) A NON-CONSTANT REFERENCE TO A CONSTANT VARIABLE :

This is just not allowed . I mention it as a matter of completeness.

Syntax: a) const type variable_name = value;


b) type *ptr_name = &variable_name;

Snippet: const int countries =250;


int *ptrToCountries= &countries;

Output: error: binding reference of type 'int&' to 'const int';

1.6 Callbacks Passing a Function To Another Function

A callback is any executable code that is passed as an argument to another code, which is
expected to call back (execute) the argument at a given time. In simple language, If a
reference of a function is passed to another function as an argument to call it, then it will be
called a Callback function.
In C, a callback function is a function that is called through a function pointer.
Below is a simple example in C to illustrate the above definition to make it more clear.

Program Example :

// A simple C program to demonstrate callback


#include <stdio.h>

void A(){
printf("I am function A\n");
}
// callback function
void B(void (*ptr)())
{
(*ptr)(); // callback to A
}

int main()
{
void (*ptr)() = &A;

// calling function B and passing


// address of the function A as argument
B(ptr);

return 0;
}

Output

I am function A

1.7 PASSING ARRAYS TO FUNCTION


How to pass an array by value, i.e., how to make sure that we have a new copy
of array when we pass it to function?

This can be done by wrapping the array in a structure and creating a variable of type
of that structure and assigning values to that array. After that, passing the variable to
some other function and modifying it as per requirements. Note that array members
are copied when passed as parameters, but dynamic arrays are not. So this solution
works only for non-dynamic arrays (created without new or malloc).

Example 1:

// C program to demonstrate passing an array


// by value using structures.

#include<stdio.h>
#include<stdlib.h>

# define SIZE 5

// A wrapper for array to make sure that array


// is passed by value.
struct ArrayWrapper
{
int arr[SIZE];
};

// An array is passed by value wrapped in temp

void modify(struct ArrayWrapper temp)


{
int *ptr = temp.arr;
int i;

// Display array contents


printf("In 'modify()', before modification\n");
for (i = 0; i < SIZE; ++i)
printf("%d ", ptr[i]);

printf("\n");

// Modify the array


for (i = 0; i < SIZE; ++i)
ptr[i] = 100; // OR *(ptr + i)

printf("\nIn 'modify()', after modification\n");


for (i = 0; i < SIZE; ++i)
printf("%d ", ptr[i]); // OR *(ptr + i)
}

// Driver code
int main()
{
int i;
struct ArrayWrapper obj;
for (i=0; i<SIZE; i++)
obj.arr[i] = 10;

modify(obj);

// Display array contents


printf("\n\nIn 'Main', after calling modify() \n");
for (i = 0; i < SIZE; ++i)
printf("%d ", obj.arr[i]); // Not changed

printf("\n");

return 0;
}

Example 2 :

#include <stdio.h>

void fun(int *arr, unsigned int n)


{
int i;
for (i=0; i<n; i++)
printf("%d ", arr[i]);
}

// Driver program
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
unsigned int n = sizeof(arr)/sizeof(arr[0]);
fun(arr, n);
return 0;
}

Output
1 2 3 4 5 6 7 8

Example 3 :

#include <stdio.h>
void fun(int *arr)
{
int i;
unsigned int n = sizeof(arr)/sizeof(arr[0]);
for (i=0; i<n; i++)
printf("%d ", arr[i]);
}

// Driver program
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
fun(arr);
return 0;
}

Output
1 2
According to the processor, the size of the pointer changes for a 32 bit computer it
assigns 4 bytes to the pointer then output becomes 1.

Example 4 :

#include <stdio.h>
#include <string.h>

void fun(char *arr)


{
int i;
unsigned int n = strlen(arr);
printf("n = %d\n", n);
for (i=0; i<n; i++)
printf("%c ", arr[i]);
}

// Driver program
int main()
{
char arr[] = "geeksquiz";
fun(arr);
return 0;
}

Output
n = 9
g e e k s q u i z

Example 5:

#include <bits/stdc++.h>
#include <iostream>
using namespace std;

void fun(char* arr)


{
int i;
unsigned int n = strlen(arr);
cout << "n = " << n << "\n";
for (i = 0; i < n; i++)
cout << " " << arr[i];
}

// Driver program
int main()
{
char arr[]
= { 'g', 'e', 'e', 'k', 's', 'q', 'u', 'i', 'z' };
fun(arr);
return 0;
}

Output

n = 9
g e e k s q u i z

NOTE: The character array in the above program is not ‘\0’


terminated. (See this for details)

b) PASS A 2D ARRAY

Example 1:

#include <stdio.h>
const int M = 3;
const int N = 3;

void print(int arr[M][N])


{
int i, j;
for (i = 0; i < M; i++)
for (j = 0; j < N; j++)
printf("%d ", arr[i][j]);
}

int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print(arr);
return 0;
}

Output
1 2 3 4 5 6 7 8 9

Example 2 :

When only the second dimension is available globally (either as a macro or as a global
constant).

#include <stdio.h>
const int N = 3;

void print(int arr[][N], int m)


{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < N; j++)
printf("%d ", arr[i][j]);
}

int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print(arr, 3);
return 0;
}

Output
1 2 3 4 5 6 7 8 9
The above method is fine if the second dimension is fixed and is not user specified. The
following methods handle cases when the second dimension can also change.

Example 3:

If compiler is C99 compatible


From C99, C language supports variable sized arrays to be passed simply by specifying the
variable dimensions .

// The following program works only if your compiler is C99


compatible.

#include <stdio.h>

// n must be passed before the 2D array


void print(int m, int n, int arr[][n])
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", arr[i][j]);
}

int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3, n = 3;
print(m, n, arr);
return 0;
}

Output

1 2 3 4 5 6 7 8 9
If the compiler is not C99 compatible, then we can use one of the following methods to pass
a variable sized 2D array.

Example 4 :

//Using a single pointer .


//In this method, we must typecast the 2D array when passing to
function.

#include <stdio.h>
void print(int *arr, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", *((arr+i*n) + j));
}

int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3, n = 3;

// We can also use "print(&arr[0][0], m, n);"


print((int *)arr, m, n);
return 0;
}

Output

1 2 3 4 5 6 7 8 9

Example 5:

// Using the concept of pointer to an array


#include <stdio.h>
const int M = 3;

void print(int (*arr)[M])


{
int i, j;
for (i = 0; i < M; i++)
for (j = 0; j < M; j++)
printf("%d ", arr[i][j]);
}

int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print(arr);
return 0;
}

Output
1 2 3 4 5 6 7 8 9

chapter

1.1 STORAGE CLASS

C Storage Classes are used to describe the features of a variable/function. These features
basically include the scope, visibility, and lifetime which help us to trace the existence of a
particular variable during the runtime of a program.
C language uses 4 storage classes, namely:

1) auto

This is the default storage class for all the variables declared inside a function or a block.
Hence, the keyword auto is rarely used while writing programs in C language. Auto variables
can be only accessed within the block/function they have been declared and not outside
them (which defines their scope). Of course, these can be accessed within nested blocks
within the parent block/function in which the auto variable was declared.
However, they can be accessed outside their scope as well using the concept of pointers
given here by pointing to the very exact memory location where the variables reside. They
are assigned a garbage value by default whenever they are declared.

2) extern

Extern storage class simply tells us that the variable is defined elsewhere and not within the
same block where it is used. Basically, the value is assigned to it in a different block and this
can be overwritten/changed in a different block as well. So an extern variable is nothing but
a global variable initialized with a legal value where it is declared in order to be used
elsewhere. It can be accessed within any function/block.
Also, a normal global variable can be made extern as well by placing the ‘extern’ keyword
before its declaration/definition in any function/block. This basically signifies that we are not
initializing a new variable but instead, we are using/accessing the global variable only. The
main purpose of using extern variables is that they can be accessed between two different
files which are part of a large program.

extern keyword in C applies to C variables (data objects) and C functions. Basically, the
extern keyword extends the visibility of the C variables and C functions. That’s probably the
reason why it was named extern.
Though most people probably understand the difference between the “declaration” and the
“definition” of a variable or function, for the sake of completeness, let’s clarify it
Declaration of a variable or function simply declares that the variable or function exists
somewhere in the program, but the memory is not allocated for them. The declaration of a
variable or function serves an important role–it tells the program what its type is going to be.
In the case of function declarations, it also tells the program the arguments, their data types,
the order of those arguments, and the return type of the function. So that’s all about the
declaration.
Coming to the definition, when we define a variable or function, in addition to everything that
a declaration does, it also allocates memory for that variable or function. Therefore, we can
think of the definition as a superset of the declaration (or declaration as a subset of the
definition).

Extern is a short name for external.

The extern variable is used when a particular files need to access a variable from another
file.

a) Syntax of extern in C
The syntax to define an extern variable in C is just to use the extern keyword before the
variable declaration.

extern data_type variable_name;

#include <stdio.h>
extern int a; // int var; -> declaration and definition
// extern int var; -> declaration

int main()
{
printf("%d", a);

return 0;
}

b) Properties of extern Variable in C

● When we write extern some_data_type some_variable_name; no memory is


allocated. Only the property of the variable is announced.

● Multiple declarations of extern variable is allowed within the file. This is not the
case with automatic variables.

● The extern variable says to the compiler “Go outside my scope and you will find
the definition of the variable that I declared.”

● The compiler believes that whatever that extern variable said is true and
produces no error. Linker throws an error when it finds no such variable exists.

● When an extern variable is initialized, then memory for this is allocated and it will
be considered defined.

A variable or function can be declared any number of times, but it can be defined only once.
(Remember the basic principle that you can’t have two locations of the same variable or
function).
Now back to the extern keyword. First, Let’s consider the use of extern in functions. It turns
out that when a function is declared or defined, the extern keyword is implicitly assumed.
When we write.

int foo(int arg1, char arg2);

The compiler treats it as:

extern int foo(int arg1, char arg2);

Since the extern keyword extends the function’s visibility to the whole program, the function
can be used (called) anywhere in any of the files of the whole program, provided those files
contain a declaration of the function. (With the declaration of the function in place, the
compiler knows the definition of the function exists somewhere else and it goes ahead and
compiles the file). So that’s all about extern and functions.
Now let’s consider the use of extern with variables. To begin with, how would you declare a
variable without defining it? You would do something like this:

extern int var;

Here, an integer-type variable called var has been declared (it hasn’t been defined yet, so no
memory allocation for var so far). And we can do this declaration as many times as we want.
Now, how would you define var? You would do this:

int var = 10;

In this line, an integer type variable called var has been both declared and defined
(remember that definition is the superset of declaration). Since this is a definition, the
memory for var is also allocated. Now here comes the surprise. When we declared/defined a
function, we saw that the extern keyword was present implicitly. But this isn’t the case with
variables. If it were, memory would never be allocated for them. Therefore, we need to
include the extern keyword explicitly when we want to declare variables without defining
them. Also, as the extern keyword extends the visibility to the whole program, by using the
extern keyword with a variable, we can use the variable anywhere in the program provided
we include its declaration the variable is defined somewhere.

Now let us try to understand extern with examples.

int var;
int main(void)
{
var = 10;
return 0;
}
—--
extern int var;
int main(void)
{
return 0;
}
—----------
extern int var;
int main(void)
{
var = 10;
return 0;
}
// As we are importing the file and henceforth the
// defination
#include "somefile.h"

// Declaring the same variable


extern int var;
// int var;
// It will throw compiler error as compiler will get
// confused where the variable is defined

int main(void)
{
var = 10;
return 0;
}

// Now it will compile and run successfully

Output:
10

Note: Here arises another scenario what if we do not declare with extern in the above code
snippet,?

Considering an assumption that somefile.h contains the definition of var, this program will
compile successfully. ‘extern’ keyword is used for a variable when we declare the variable in
one file and define it in another file. But here when we import the same file in the file where it
is declared, here compiler error will be generated.

It is because we still have to use the extern keyword in the file where we have declared that
variable so as to tell our compiler that this variable is been defined somewhere else than
only new memory space will not be allocated else it will create another memory block which
usage of ‘extern’ keyword useless.

extern int var = 0;


int main(void)
{
var = 10;
return 0;
}
Do you think this program will work? Well, here comes another surprise from C standards.
They say that..if a variable is only declared and an initializer is also provided with that
declaration, then the memory for that variable will be allocated–in other words, that variable
will be considered as defined. Therefore, as per the C standard, this program will compile
successfully and work.
So that was a preliminary look at the extern keyword in C.

In short, we can say:

1. A declaration can be done any number of times but defined only once.

2. the extern keyword is used to extend the visibility of variables/functions.

3. Since functions are visible throughout the program by default, the use of the
extern is not needed in function declarations or definitions. Its use is implicit.

4. When extern is used with a variable, it’s only declared, not defined.

5. As an exception, when an extern variable is declared with initialization, it is taken


as the definition of the variable as well.

3) static

This storage class is used to declare static variables which are popularly used while writing
programs in C language. Static variables have the property of preserving their value even
after they are out of their scope! Hence, static variables preserve the value of their last use
in their scope. So we can say that they are initialized only once and exist till the termination
of the program. Thus, no new memory is allocated because they are not re-declared.
Their scope is local to the function to which they were defined. Global static variables can be
accessed anywhere in the program. By default, they are assigned the value 0 by the
compiler.
Static variables have the property of preserving their value even after they are out of their
scope! Hence, a static variable preserves its previous value in its previous scope and is not
initialized again in the new scope.
a) Syntax:

static data_type var_name = var_value;

Initialization of static variables in C

#include<stdio.h>

int initializer(void)
{
return 50;
}

int main()
{
static int i = initializer();
printf(" value of i = %d", i);
getchar();
return 0;
}

If we change the program to the following, then it works without any


error.
#include<stdio.h>
int main()
{
static int i = 50;
printf(" value of i = %d", i);
getchar();
return 0;
}

The reason for this is simple: All objects with static storage duration must be initialized (set
to their initial values) before execution of main() starts. So a value which is not known at
translation time cannot be used for initialization of static variables.

b) Following are some interesting facts about static variables in C:

● A static int variable remains in memory while the program is running. A normal or
auto variable is destroyed when a function call where the variable was declared is
over.
For example, we can use static int to count the number of times a function is called,
but an auto variable can’t be used for this purpose.

Example 1:

// C Program to illustrate the static variable lifetime

#include <stdio.h>

// function with static variable


int fun()
{
static int count = 0;
count++;
return count;
}

int main()
{
printf("%d ", fun());
printf("%d ", fun());
return 0;
}

Output

This will generate an error in C but no error in C++.

Example 2 :

// C++ Program to Implement Member functions inside


// structure

#include <iostream>
using namespace std;

struct marks {
int num;

// Member function inside Structure to


// take input and store it in "num"
void Set(int temp) { num = temp; }

// function used to display the values


void display() { cout << "num=" << num; }
};

// Driver Program
int main()
{
marks m1;

// calling function inside Struct to


// initialize value to num
m1.Set(9);

// calling function inside struct to


// display value of Num
m1.display();
}

Output

1 2

The above program prints 1 2 because static variables are only initialized once and live till
the end of the program. That is why they can retain their value between multiple function
calls.
Let’s try the same code for the local auto variable.

Example 3 :

// C Program to illustrate local auto variable in comparison


// of static variable.

#include <stdio.h>

// Function
int fun()
{
int count = 0;
count++;
return count;
}

// Driver Code
int main()
{
printf("%d ", fun());
printf("%d ", fun());
return 0;
}

Output
1 1

● Static variables are allocated memory in the data segment, not the stack
segment. See the memory layout of C programs for details.Static variables
(like global variables) are initialized as 0 if not initialized explicitly. For
example in the below program, the value of x is printed as 0, while the value
of y is something garbage. See this for more details.

Example 1 :
// C program to illustrate the default value of static
// variables
#include <stdio.h>

int main()
{
static int x;
int y;
printf("%d \n%d", x, y);
}

Output
0
[some_garbage_value]

● In C, static variables can only be initialized using constant literals. For example, the
following program fails in the compilation. See this for more details.

Example 1:
#include<stdio.h>
int initializer(void)
{
return 50;
}
int main()
{
static int i = initializer();
printf(" value of i = %d", i);
getchar();
return 0;
}

Output
In function 'main':
9:5: error: initializer element is not constant
static int i = initializer();
^
Note: Please note that this condition doesn’t hold in C++. So if you save the program as a
C++ program, it would compile and run fine.

● Static global variables and functions are also possible in C/C++. The purpose of
these is to limit the scope of a variable or function to a file. Please refer to Static
functions in C for more details.

● Static variables should not be declared inside a structure. The reason is C compiler
requires the entire structure elements to be placed together (i.e.) memory allocation
for structure members should be contiguous. It is possible to declare structure inside
the function (stack segment) or allocate memory dynamically(heap segment) or it can
be even global (BSS or data segment). Whatever might be the case, all structure
members should reside in the same memory segment because the value for the
structure element is fetched by counting the offset of the element from the beginning
address of the structure. Separating out one member alone to a data segment
defeats the purpose of structure and it is possible to have an entire structure as
static.

c) Static functions

In C, functions are global by default. The “static” keyword before a function name makes it
static.

For example, the below function fun() is static.


static int fun(void) {
printf("I am a static function ");
}

Unlike global functions in C, access to static functions is restricted to the file where they
are declared. Therefore, when we want to restrict access to functions, we make them static.
Another reason for making functions static can be the reuse of the same function name in
other files.

For example, if we store the following program in one file file1.c

/* Inside file1.c */
static void fun1(void) {
puts("fun1 called");
}

And store the following program in another file file2.c

/* Inside file2.c */
int main(void)
{
fun1();
getchar();
return 0;
}

Now, if we compile the above code with the command “gcc file2.c file1.c”, we get the error
“undefined reference to `fun1’”. This is because fun1() is declared static in file1.c and cannot
be used in file2.c.

In C, functions are global by default. The “static” keyword before a function name makes it
static.

For example, the below function fun() is static.

static int fun(void) {


printf("I am a static function ");
}

Unlike global functions in C, access to static functions is restricted to the file where they
are declared. Therefore, when we want to restrict access to functions, we make them static.
Another reason for making functions static can be the reuse of the same function name in
other files.

For example, if we store the following program in one file file1.c

/* Inside file1.c */
static void fun1(void) {
puts("fun1 called");
}

And store the following program in another file file2.c

/* Inside file2.c */
int main(void)
{
fun1();
getchar();
return 0;
}

Now, if we compile the above code with the command “gcc file2.c file1.c”, we get the error
“undefined reference to `fun1’”. This is because fun1() is declared static in file1.c and cannot
be used in file2.c.

4) register

This storage class declares register variables that have the same functionality as that of the
auto variables. The only difference is that the compiler tries to store these variables in the
register of the microprocessor if a free register is available. This makes the use of register
variables to be much faster than that of the variables stored in the memory during the
runtime of the program.
If a free registration is not available, these are then stored in the memory only. Usually, a few
variables which are to be accessed very frequently in a program are declared with the
register keyword which improves the running time of the program. An important and
interesting point to be noted here is that we cannot obtain the address of a register variable
using pointers.

a) Understanding “register” keyword in C

Registers are faster than memory to access, so the variables which are most frequently used
in a C program can be put in registers using the register keyword. The keyword register
hints to the compiler that a given variable can be put in a register. It’s the compiler’s choice
to put it in a register or not. Generally, compilers themselves do optimizations and put the
variables in a register.
b) Following are some interesting facts about the “register” keyword in C:

● If you use & operator with a register variable then the compiler may give an error or
warning (depending upon the compiler you are using), because when we say a
variable is a register, it may be stored in a register instead of memory and accessing
the address of a register is invalid.

Try the below program:

// C program that demonstrates accessing the address of a


// register is invalid

#include <stdio.h>

int main()
{
// Declaring a register variable 'i' and initializing it
// with 10
register int i = 10;
// Creating a pointer variable 'a' and assigning the
// address of 'i' to it
int* a = &i;
printf("%d", *a);
getchar();
return 0;
}

Output
./Solution.c: In function 'main':
./Solution.c:6:5: error: address of register variable 'i' requested
int* a = &i;
● register keyword can be used with pointer variables. Obviously, a register can have
the address of a memory location. There would not be any problem with the below
program.

Example :

// C program that demonstrates register keyword can be used


// with pointer variables

#include <stdio.h>

int main()
{
// Declaring an integer variable 'i' and initializing it
// with 10
int i = 10;
// Declaring a register pointer variable 'a' and
// assigning the address of 'i' to it
register int* a = &i;
printf("%d", *a);
getchar();
return 0;
}

Output

10

● Register is a storage class, and C doesn’t allow multiple storage class specifiers for
a variable. So, the register can not be used with static.

Try the below program:


// C program that demonstrates register can not be used with
// static

#include <stdio.h>

int main()
{
// Declaring an integer variable 'i' and initializing it
// with 10
int i = 10;

// ERROR: Attempting to use both register and static


// storage classes for 'a'

register static int* a = &i;


printf("%d", *a);
getchar();
return 0;
}

Output
./Solution.c: In function 'main':
./Solution.c:6:5: error: multiple storage classes in declaration
specifiers
register static int* a = &i;

● Register can only be used within a block (local), it can not be used in the global
scope (outside main).
Example:
#include <stdio.h>

// error (global scope)


register int x = 10;
int main()
{
// works (inside a block)
register int i = 10;
printf("%d\n", i);
printf("%d", x);
return 0;
}

Output
./Solution.c:4:14: error: register name not specified for 'x'
register int x = 10;
^
● There is no limit on the number of register variables in a C program, but the point is
the compiler may put some variables in the register and some not. Please write
comments if you find anything incorrect in the above article or you want to share
more information about register keyword.

a) Syntax

To specify the storage class for a variable, the following syntax is to be followed:

storage_class var_data_type var_name;

Example:

// A C program to demonstrate different storage


// classes

#include <stdio.h>

// declaring the variable which is to be made extern


// an initial value can also be initialized to x
int x;

void autoStorageClass()
{
printf("\nDemonstrating auto class\n\n");

// declaring an auto variable (simply


// writing "int a=32;" works as well)
auto int a = 32;

// printing the auto variable 'a'


printf("Value of the variable 'a'"
" declared as auto: %d\n",
a);

printf("--------------------------------");
}

void registerStorageClass() {
printf("\nDemonstrating register class\n\n");

// declaring a register variable


register char b = 'G';

// printing the register variable 'b'


printf("Value of the variable 'b'"
" declared as register: %d\n",
b);

printf("--------------------------------");
}

void externStorageClass()
{
printf("\nDemonstrating extern class\n\n");

// telling the compiler that the variable


// x is an extern variable and has been
// defined elsewhere (above the main
// function)
extern int x;

// printing the extern variables 'x'


printf("Value of the variable 'x'"
" declared as extern: %d\n",
x);

// value of extern variable x modified


x = 2;

// printing the modified values of


// extern variables 'x'
printf("Modified value of the variable 'x'"
" declared as extern: %d\n",
x);

printf("--------------------------------");
}

void staticStorageClass()
{
int i = 0;
printf("\nDemonstrating static class\n\n");

// using a static variable 'y'


printf("Declaring 'y' as static inside the loop.\n"
"But this declaration will occur only"
" once as 'y' is static.\n"
"If not, then every time the value of 'y' "
"will be the declared value 5"
" as in the case of variable 'p'\n");

printf("\nLoop started:\n");

for (i = 1; i < 5; i++) {

// Declaring the static variable 'y'


static int y = 5;

// Declare a non-static variable 'p'


int p = 10;

// Incrementing the value of y and p by 1


y++;
p++;

// printing value of y at each iteration


printf("\nThe value of 'y', "
"declared as static, in %d "
"iteration is %d\n",
i, y);

// printing value of p at each iteration


printf("The value of non-static variable 'p', "
"in %d iteration is %d\n",
i, p);
}

printf("\nLoop ended:\n");

printf("--------------------------------");
}

int main()
{

printf("A program to demonstrate"


" Storage Classes in C\n\n");

// To demonstrate auto Storage Class


autoStorageClass();

// To demonstrate register Storage Class


registerStorageClass();

// To demonstrate extern Storage Class


externStorageClass();

// To demonstrate static Storage Class


staticStorageClass();

// exiting
printf("\n\nStorage Classes demonstrated");

return 0;
}

Output

A program to demonstrate Storage Classes in C

Demonstrating auto class

Value of the variable 'a' declared as auto: 32


--------------------------------
Demonstrating register class

Value of the variable 'b' declared as register: 71


--------------------------------
Demonstrating extern class

Value of the variable 'x' declared as extern: 0


Modified value of the variable 'x' declared as extern: 2
--------------------------------
Demonstrating static class

Declaring 'y' as static inside the loop.


But this declaration will occur only once as 'y' is static.
If not, then every time the value of 'y' will be the declared value 5 as in the case of variable
'p'

Loop started:

The value of 'y', declared as static, in 1 iteration is 6


The value of non-static variable 'p', in 1 iteration is 11
The value of 'y', declared as static, in 2 iteration is 7
The value of non-static variable 'p', in 2 iteration is 11

The value of 'y', declared as static, in 3 iteration is 8


The value of non-static variable 'p', in 3 iteration is 11

The value of 'y', declared as static, in 4 iteration is 9


The value of non-static variable 'p', in 4 iteration is 11

Loop ended:
chapter
chapter

FILE HANDLING

1. Types of Files in C

A file can be classified into two types based on the way the file stores the data. They are as
follows:

● Text Files

● Binary Files

Text Files

A text file contains data in the form of ASCII characters and is generally used to store a
stream of characters.
● Each line in a text file ends with a new line character (‘\n’).

● It can be read or written by any text editor.

● They are generally stored with .txt file extension.

● Text files can also be used to store the source code.

Binary Files

A binary file contains data in binary form (i.e. 0’s and 1’s) instead of ASCII characters. They
contain data that is stored in a similar manner to how it is stored in the main memory.

● The binary files can be created only from within a program and their contents can
only be read by a program.

● More secure as they are not easily readable.

● They are generally stored with .bin file extension.

1.1 C File Operations


C file operations refer to the different possible operations that we can perform on a file in C
such as:

1. Creating a new file – fopen() with attributes as “a” or “a+” or “w” or “w+”

2. Opening an existing file – fopen()

3. Reading from file – fscanf() or fgets()

4. Writing to a file – fprintf() or fputs()

5. Moving to a specific location in a file – fseek(), rewind()

6. Closing a file – fclose()


The highlighted text mentions the C function used to perform the file operations.

Functions for C File Operations

1.2 File Pointer in C


A file pointer is a reference to a particular position in the opened file. It is used in file
handling to perform all file operations such as read, write, close, etc. We use the FILE macro
to declare the file pointer variable. The FILE macro is defined inside <stdio.h> header file.

Syntax of File Pointer

FILE* pointer_name;

File Pointer is used in almost all the file operations in C.


1.3 Open a File in C

For opening a file in C, the fopen() function is used with the filename or file path along with
the required access modes.

Syntax of fopen()

FILE* fopen(const char *file_name, const char *access_mode);

Parameters

● file_name: name of the file when present in the same directory as the source file.
Otherwise, full path.

● access_mode: Specifies for what operation the file is being opened.

Return Value

● If the file is opened successfully, returns a file pointer to it.

● If the file is not opened, then returns NULL.

a) File opening modes in C

File opening modes or access modes specify the allowed operations on the file to be
opened. They are passed as an argument to the fopen() function. Some of the commonly
used file access modes are listed below:

As given above, if you want to perform operations on a binary file, then you have to append
‘b’ at the last. For example, instead of “w”, you have to use “wb”, instead of “a+” you have to
use “a+b”.
Opening
Description
Modes

Searches file. If the file is opened successfully fopen( ) loads

it into memory and sets up a pointer that points to the first


r
character in it. If the file cannot be opened fopen( ) returns

NULL.

Open for reading in binary mode. If the file does not exist,
rb
fopen( ) returns NULL.

Open for reading in text mode. If the file exists, its contents

w are overwritten. If the file doesn’t exist, a new file is created.

Returns NULL, if unable to open the file.

wb Open for writing in binary mode. If the file exists, its

contents are overwritten. If the file does not exist, it will be


created.

Searches file. If the file is opened successfully fopen( ) loads

it into memory and sets up a pointer that points to the last

a character in it. It opens only in the append mode. If the file

doesn’t exist, a new file is created. Returns NULL, if unable

to open the file.

Open for append in binary mode. Data is added to the end


ab
of the file. If the file does not exist, it will be created.

Searches file. It is opened successfully fopen( ) loads it into

r+ memory and sets up a pointer that points to the first

character in it. Returns NULL, if unable to open the file.

Open for both reading and writing in binary mode. If the file
rb+
does not exist, fopen( ) returns NULL.
Searches file. If the file exists, its contents are overwritten. If

w+ the file doesn’t exist a new file is created. Returns NULL, if

unable to open the file.

Open for both reading and writing in binary mode. If the file

wb+ exists, its contents are overwritten. If the file does not exist,

it will be created.

Searches file. If the file is opened successfully fopen( ) loads

it into memory and sets up a pointer that points to the last

a+ character in it. It opens the file in both reading and append

mode. If the file doesn’t exist, a new file is created. Returns

NULL, if unable to open the file.

Open for both reading and appending in binary mode. If the


ab+
file does not exist, it will be created.
Example of Opening a File

// C Program to illustrate file opening

#include <stdio.h>

#include <stdlib.h>

int main()

// file pointer variable to store the value returned by

// fopen

FILE* fptr;

// opening the file in read mode

fptr = fopen("filename.txt", "r");

// checking if the file is opened successfully

if (fptr == NULL) {

printf("The file is not opened. The program will "

"now exit.");

exit(0);

return 0;

Output : The file is not opened. The program will now exit.
The file is not opened because it does not exist in the source directory. But the fopen()
function is also capable of creating a file if it does not exist. It is shown below

1.4 Create a File in C

The fopen() function can not only open a file but also can create a file if it does not exist
already. For that, we have to use the modes that allow the creation of a file if not found such
as w, w+, wb, wb+, a, a+, ab, and ab+.

FILE *fptr;
fptr = fopen("filename.txt", "w");

// C Program to create a file


#include <stdio.h>
#include <stdlib.h>

int main()
{
// file pointer
FILE* fptr;

// creating file using fopen() access mode "w"


fptr = fopen("file.txt", "w");

// checking if the file is created


if (fptr == NULL) {
printf("The file is not opened. The program will "
"exit now");
exit(0);
}
else {
printf("The file is created Successfully.");
}

return 0;
}

Output
The file is created Successfully.

1.5 Reading From a File


The file read operation in C can be performed using functions fscanf() or fgets(). Both the
functions performed the same operations as that of scanf and gets but with an additional
parameter, the file pointer. There are also other functions we can use to read from a file.
Such functions are listed below:

So, it depends on you if you want to read the file line by line or character by character.

Example:

FILE * fptr;

fptr = fopen(“fileName.txt”, “r”);

fscanf(fptr, "%s %s %s %d", str1, str2, str3, &year);

char c = fgetc(fptr);

The getc() and some other file reading functions return EOF (End Of File) when they reach
the end of the file while reading. EOF indicates the end of the file and its value is
implementation-defined.

Note: One thing to note here is that after reading a particular part of the file, the file pointer
will be automatically moved to the end of the last read character.

1.6 Write to a File


The file write operations can be performed by the functions fprintf() and fputs() with
similarities to read operations. C programming also provides some other functions that can
be used to write data to a file such as:

Example:

FILE *fptr ;
fptr = fopen(“fileName.txt”, “w”);
fprintf(fptr, "%s %s %s %d", "We", "are", "in", 2012);
fputc("a", fptr);

1.7 Closing a File

The fclose() function is used to close the file. After successful file operations, you must
always close a file to remove it from the memory.

Syntax of fclose()

fclose(file_pointer);

where the file_pointer is the pointer to the opened file.


Example:

FILE *fptr ;

fptr= fopen(“fileName.txt”, “w”);

---------- Some file Operations -------

fclose(fptr);

1.8 Examples of File Handing in C

Example 1: Program to Create a File, Write in it, And Close the File

// C program to Open a File,


// Write in it, And Close the File
#include <stdio.h>
#include <string.h>

int main()
{

// Declare the file pointer


FILE* filePointer;

// Get the data to be written in file


char dataToBeWritten[50] = "GeeksforGeeks-A Computer "
"Science Portal for Geeks";

// Open the existing file GfgTest.c using fopen()


// in write mode using "w" attribute
filePointer = fopen("GfgTest.c", "w");

// Check if this filePointer is null


// which maybe if the file does not exist
if (filePointer == NULL) {
printf("GfgTest.c file failed to open.");
}
else {

printf("The file is now opened.\n");

// Write the dataToBeWritten into the file

if (strlen(dataToBeWritten) > 0) {
// writing in the file using fputs()
fputs(dataToBeWritten, filePointer);
fputs("\n", filePointer);
}

// Closing the file using fclose()


fclose(filePointer);

printf("Data successfully written in file "


"GfgTest.c\n");
printf("The file is now closed.");
}

return 0;
}

Output
The file is now opened.
Data successfully written in file GfgTest.c
The file is now closed.

This program will create a file named GfgTest.c in the same directory as the source file
which will contain the following text: “GeeksforGeeks-A Computer Science Portal for Geeks”.

Example 2: Program to Open a File, Read from it, And Close the File

// C program to Open a File,


// Read from it, And Close the File
#include <stdio.h>
#include <string.h>

int main()
{

// Declare the file pointer


FILE* filePointer;

// Declare the variable for the data to be read from


// file
char dataToBeRead[50];

// Open the existing file GfgTest.c using fopen()


// in read mode using "r" attribute
filePointer = fopen("GfgTest.c", "r");
// Check if this filePointer is null
// which maybe if the file does not exist
if (filePointer == NULL) {
printf("GfgTest.c file failed to open.");
}
else {

printf("The file is now opened.\n");

// Read the dataToBeRead from the file


// using fgets() method
while (fgets(dataToBeRead, 50, filePointer)
!= NULL) {

// Print the dataToBeRead


printf("%s", dataToBeRead);
}

// Closing the file using fclose()


fclose(filePointer);

printf(
"Data successfully read from file GfgTest.c\n");
printf("The file is now closed.");
}
return 0;
}

Output

The file is now opened.


GeeksforGeeks-A Computer Science Portal for Geeks
Data successfully read from file GfgTest.c
The file is now closed.

This program reads the text from the file named GfgTest.c which we created in the previous
example and prints it in the console.

Binary Files

1. Read and Write in a Binary File

Till now, we have only discussed text file operations. The operations on a binary file are
similar to text file operations with little difference.
1.1 Opening a Binary File

To open a file in binary mode, we use the rb, rb+, ab, ab+, wb, and wb+ access mode in the
fopen() function. We also use the .bin file extension in the binary filename.

Example

fptr = fopen("filename.bin", "rb");

1.2 Write to a Binary File

We use fwrite() function to write data to a binary file. The data is written to the binary file in
the from of bits (0’s and 1’s).

Syntax of fwrite()

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE


*file_pointer);

Parameters:

● ptr: pointer to the block of memory to be written.


● size: size of each element to be written (in bytes).
● nmemb: number of elements.
● file_pointer: FILE pointer to the output file stream.

Return Value:

● Number of objects written.

Example:

// C program to write to a Binary file using fwrite()

#include <stdio.h>
#include <stdlib.h>
struct threeNum {
int n1, n2, n3;
};
int main()
{
int n;
// Structure variable declared here.
struct threeNum num;
FILE* fptr;
if ((fptr = fopen("C:\\program.bin", "wb")) == NULL) {
printf("Error! opening file");
// If file pointer will return NULL
// Program will exit.
exit(1);
}
int flag = 0;
int flag = 0;
// else it will return a pointer to the file.
for (n = 1; n < 5; ++n) {
num.n1 = n;
num.n2 = 5 * n;
num.n3 = 5 * n + 1;
flag = fwrite(&num, sizeof(struct threeNum), 1,
fptr);

// checking if the data is written


if (!flag) {
printf("Write Operation Failure");
}
else {
printf("Write Operation Successful");
}

fclose(fptr);

return 0;
}

Output

Write Operation Successful

1.3 Reading from Binary File

The fread() function can be used to read data from a binary file in C. The data is read from
the file in the same form as it is stored i.e. binary form.
Syntax of fread()

size_t fread(void *ptr, size_t size, size_t nmemb, FILE


*file_pointer);

Parameters:

● ptr: pointer to the block of memory to read.


● size: the size of each element to read(in bytes).
● nmemb: number of elements.
● file_pointer: FILE pointer to the input file stream.

Return Value:

● Number of objects written.

Example:

// C Program to Read from a binary file using fread()

#include <stdio.h>

#include <stdlib.h>

struct threeNum {

int n1, n2, n3;

};

int main()

int n;

struct threeNum num;

FILE* fptr;

if ((fptr = fopen("C:\\program.bin", "rb")) == NULL) {


printf("Error! opening file");

// If file pointer will return NULL

// Program will exit.

exit(1);

// else it will return a pointer to the file.

for (n = 1; n < 5; ++n) {

fread(&num, sizeof(struct threeNum), 1, fptr);

printf("n1: %d\tn2: %d\tn3: %d\n", num.n1, num.n2,

num.n3);

fclose(fptr);

return 0;

Output

n1: 1 n2: 5 n3: 6

n1: 2 n2: 10 n3: 11

n1: 3 n2: 15 n3: 16

n1: 4 n2: 20 n3: 21

1.4 fseek() in C

If we have multiple records inside a file and need to access a particular record that is at a
specific position, so we need to loop through all the records before it to get the record. Doing
this will waste a lot of memory and operational time. To reduce memory consumption and
operational time we can use fseek() which provides an easier way to get to the required
data. fseek() function in C seeks the cursor to the given record in the file.

a) Syntax for fseek()

int fseek(FILE *ptr, long int offset, int pos);

Example :

// C program to illustrate the use of rewind

#include <stdio.h>

int main()
{
FILE* fptr;
fptr = fopen("file.txt", "w+");
fprintf(fptr, "Geeks for Geeks\n");

// using rewind()
rewind(fptr);

// reading from file


char buf[50];
fscanf(fptr, "%[^\n]s", buf);

printf("%s", buf);

return 0;
}

Output
81

More Functions for C File Operations

The following table lists some more functions that can be used to perform file operations or
assist in performing them.
Functions Description

fopen() It is used to create a file or to open a file.

fclose() It is used to close a file.

fgets() It is used to read a file.

fprintf() It is used to write blocks of data into a file.

fscanf() It is used to read blocks of data from a file.

getc() It is used to read a single character to a file.

putc() It is used to write a single character to a file.


It is used to set the position of a file pointer to a mentioned
fseek()
location.

ftell() It is used to return the current position of a file pointer.

rewind() It is used to set the file pointer to the beginning of a file.

putw() It is used to write an integer to a file.

It is used to read an integer from a file.

getw()
chapter

1. Memory Management

A typical memory representation of a C program consists of the following sections.

1) Text segment (i.e. instructions)


2) Initialized data segment
3) Uninitialized data segment (bss)
4) Heap
5) Stack

A typical memory layout of a running process

1) Text Segment: A text segment, also known as a code segment or simply as text, is
one of the sections of a program in an object file or in memory, which contains
executable instructions.
As a memory region, a text segment may be placed below the heap or stack in order
to prevent heaps and stack overflows from overwriting it. Usually, the text segment is
sharable so that only a single copy needs to be in memory for frequently executed
programs, such as text editors, the C compiler, the shells, and so on. Also, the text
segment is often read-only, to prevent a program from accidentally modifying its
instructions.
2) Initialized Data Segment: Initialized data segment, usually called simply the Data
Segment. A data segment is a portion of the virtual address space of a program,
which contains the global variables and static variables that are initialized by the
programmer.
Note that, the data segment is not read-only, since the values of the variables can be
altered at run time. This segment can be further classified into the initialized read-
only area and the initialized read-write area.

For instance, the global string defined by char s[] = “hello world” in C and a C
statement like int debug=1 outside the main (i.e. global) would be stored in the
initialized read-write area. And a global C statement like const char* string = “hello
world” makes the string literal “hello world” to be stored in the initialized read-only
area and the character pointer variable string in the initialized read-write area.

Ex: static int i = 10 will be stored in the data segment and global
int i = 10 will also be stored in data segment

3) Uninitialized Data Segment: Uninitialized data segment often called the “bss”
segment, named after an ancient assembler operator that stood for “block started by
symbol.” Data in this segment is initialized by the kernel to arithmetic 0 before the
program starts executing uninitialized data starts at the end of the data segment and
contains all global variables and static variables that are initialized to zero or do not
have explicit initialization in source code.
For instance, a variable declared static int i; would be contained in the BSS segment.

For instance, a global variable declared int j; would be contained in the BSS
segment.

4) Stack: The stack area traditionally adjoined the heap area and grew in the opposite
direction; when the stack pointer met the heap pointer, free memory was exhausted.
(With modern large address spaces and virtual memory techniques they may be
placed almost anywhere, but they still typically grow in opposite directions.)
The stack area contains the program stack, a LIFO structure, typically located in the
higher parts of memory. On the standard PC x86 computer architecture, it grows
toward address zero; on some other architectures, it grows in the opposite direction.
A “stack pointer” register tracks the top of the stack; it is adjusted each time a value
is “pushed” onto the stack. The set of values pushed for one function call is termed a
“stack frame”; A stack frame consists at minimum of a return address.
Stack, where automatic variables are stored, along with information that is saved
each time a function is called. Each time a function is called, the address of where to
return to and certain information about the caller’s environment, such as some of the
machine registers, are saved on the stack. The newly called function then allocates
room on the stack for its automatic variables. This is how recursive functions in C can
work. Each time a recursive function calls itself, a new stack frame is used, so one
set of variables doesn’t interfere with the variables from another instance of the
function.

5) Heap: Heap is the segment where dynamic memory allocation usually takes place.
The heap area begins at the end of the BSS segment and grows to larger addresses
from there. The Heap area is managed by malloc, realloc, and free, which may use
the brk and sbrk system calls to adjust its size (note that the use of brk/sbrk and a
single “heap area” is not required to fulfill the contract of malloc/realloc/free; they may
also be implemented using mmap to reserve potentially non-contiguous regions of
virtual memory into the process’ virtual address space). The Heap area is shared by
all shared libraries and dynamically loaded modules in a process.

Examples:

The size(1) command reports the sizes (in bytes) of the text, data, and bss segments. ( for
more details please refer man page of size(1) )

a) Check the following simple C program


b)
#include <stdio.h>

int main(void)
{
return 0;
}

[narendra@CentOS]$ gcc memory-layout.c -o memory-layout


[narendra@CentOS]$ size memory-layout
text data bss dec hex filename
960 248 8 1216 4c0 memory-layout

b) Let us add one global variable in the program, now check the size of bss (highlighted in
red color).

#include <stdio.h>

int global; /* Uninitialized variable stored in bss*/

int main(void)
{
return 0;
}
[narendra@CentOS]$ gcc memory-layout.c -o memory-layout
[narendra@CentOS]$ size memory-layout
text data bss dec hex filename
960 248 12 1220 4c4 memory-layout

c)Let us add one static variable which is also stored in bss.

#include <stdio.h>

int global; /* Uninitialized variable stored in bss*/

int main(void)
{
static int i; /* Uninitialized static variable stored in bss
*/
return 0;
}

[narendra@CentOS]$ gcc memory-layout.c -o memory-layout


[narendra@CentOS]$ size memory-layout
text data bss dec hex filename
960 248 16 1224 4c8 memory-layout

d) Let us initialize the static variable which will then be stored in the Data Segment
(DS)

#include <stdio.h>

int global; /* Uninitialized variable stored in bss*/

int main(void)
{
static int i = 100; /* Initialized static variable stored in
DS*/
return 0;
}

[narendra@CentOS]$ gcc memory-layout.c -o memory-layout


[narendra@CentOS]$ size memory-layout
text data bss dec hex filename
960 252 12 1224 4c8 memory-layout

f) Let us initialize the global variable which will then be stored in the Data Segment
(DS)

#include <stdio.h>
int global = 10; /* initialized global variable stored in DS*/

int main(void)
{
static int i = 100; /* Initialized static variable stored in
DS*/
return 0;
}

[narendra@CentOS]$ gcc memory-layout.c -o memory-layout


[narendra@CentOS]$ size memory-layout
text data bss dec hex filename
960 256 8 1224 4c8 memory-layout

1.2 Dynamic Memory Allocation in C using malloc(), calloc(), free() and


realloc()

Since C is a structured language, it has some fixed rules for programming. One of them
includes changing the size of an array. An array is a collection of items stored at contiguous
memory locations.

As can be seen, the length (size) of the array above is 9. But what if there is a requirement
to change this length (size)?

For example,

● If there is a situation where only 5 elements are needed to be entered in this array. In
this case, the remaining 4 indices are just wasting memory in this array. So there is a
requirement to lessen the length (size) of the array from 9 to 5.

● Take another situation. In this, there is an array of 9 elements with all 9 indices filled.
But there is a need to enter 3 more elements in this array. In this case, 3 indices
more are required. So the length (size) of the array needs to be changed from 9 to
12.
This procedure is referred to as Dynamic Memory Allocation in C.

Therefore, C Dynamic Memory Allocation can be defined as a procedure in which the size of
a data structure (like Array) is changed during the runtime.
C provides some functions to achieve these tasks. There are 4 library functions provided by
C defined under <stdlib.h> header file to facilitate dynamic memory allocation in C
programming. They are:

1. malloc()
2. calloc()
3. free()
4. realloc()

Let’s look at each of them in greater detail.

1.3 C malloc() method

The “malloc” or “memory allocation” method in C is used to dynamically allocate a single


large block of memory with the specified size. It returns a pointer of type void which can be
cast into a pointer of any form. It doesn’t Initialize memory at execution time so that it has
initialized each block with the default garbage value initially.

a) Syntax of malloc() in C

ptr = (cast-type*) malloc(byte-size)


For Example:

ptr = (int*) malloc(100 * sizeof(int));

Since the size of int is 4 bytes, this statement will allocate 400 bytes of memory. And, the
pointer ptr holds the address of the first byte in the allocated memory.
If space is insufficient, allocation fails and returns a NULL pointer.

Example of malloc() in C

#include <stdio.h>
#include <stdlib.h>

int main()
{

// This pointer will hold the


// base address of the block created
int* ptr;
int n, i;

// Get the number of elements for the array


printf("Enter number of elements:");
scanf("%d",&n);
printf("Entered number of elements: %d\n", n);

// Dynamically allocate memory using malloc()


ptr = (int*)malloc(n * sizeof(int));

// Check if the memory has been successfully


// allocated by malloc or not
if (ptr == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {

// Memory has been successfully allocated


printf("Memory successfully allocated using malloc.\n");

// Get the elements of the array


for (i = 0; i < n; ++i) {
ptr[i] = i + 1;
}

// Print the elements of the array


printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}
}

return 0;
}

Output

Enter number of elements: 5


Memory successfully allocated using malloc.
The elements of the array are: 1, 2, 3, 4, 5,

1.4 C calloc() method

1) “calloc” or “contiguous allocation” method in C is used to dynamically allocate


the specified number of blocks of memory of the specified type. it is very
much similar to malloc() but has two different points and these are:

2) It initializes each block with a default value ‘0’.


3) It has two parameters or arguments as compared to malloc().

a) Syntax of calloc() in C

ptr = (cast-type*)calloc(n, element-size);


here, n is the no. of elements and element-size is the size of each
element.

For Example:

ptr = (float*) calloc(25, sizeof(float));


This statement allocates contiguous space in memory for 25 elements
each with the size of the float.
If space is insufficient, allocation fails and returns a NULL pointer.

Example of calloc() in C

#include <stdio.h>
#include <stdlib.h>

int main()
{

// This pointer will hold the


// base address of the block created
int* ptr;
int n, i;

// Get the number of elements for the array


n = 5;
printf("Enter number of elements: %d\n", n);

// Dynamically allocate memory using calloc()


ptr = (int*)calloc(n, sizeof(int));

// Check if the memory has been successfully


// allocated by calloc or not
if (ptr == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {

// Memory has been successfully allocated


printf("Memory successfully allocated using calloc.\n");

// Get the elements of the array


for (i = 0; i < n; ++i) {
ptr[i] = i + 1;
}

// Print the elements of the array


printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}
}

return 0;
}

Output

Enter number of elements: 5


Memory successfully allocated using calloc.
The elements of the array are: 1, 2, 3, 4, 5,

1.5 C free() method

“free” method in C is used to dynamically de-allocate the memory. The memory allocated
using functions malloc() and calloc() is not de-allocated on their own. Hence the free()
method is used, whenever the dynamic memory allocation takes place. It helps to reduce
wastage of memory by freeing it.

a) Syntax of free() in C

free(ptr);
Example of free() in C

#include <stdio.h>
#include <stdlib.h>

int main()
{

// This pointer will hold the


// base address of the block created
int *ptr, *ptr1;
int n, i;

// Get the number of elements for the array


n = 5;
printf("Enter number of elements: %d\n", n);

// Dynamically allocate memory using malloc()


ptr = (int*)malloc(n * sizeof(int));

// Dynamically allocate memory using calloc()


ptr1 = (int*)calloc(n, sizeof(int));

// Check if the memory has been successfully


// allocated by malloc or not
if (ptr == NULL || ptr1 == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {

// Memory has been successfully allocated


printf("Memory successfully allocated using malloc.\n");

// Free the memory


free(ptr);
printf("Malloc Memory successfully freed.\n");

// Memory has been successfully allocated


printf("\nMemory successfully allocated using calloc.\
n");

// Free the memory


free(ptr1);
printf("Calloc Memory successfully freed.\n");
}

return 0;
}

Output

Enter number of elements: 5


Memory successfully allocated using malloc.
Malloc Memory successfully freed.

Memory successfully allocated using calloc.


Calloc Memory successfully freed.

1.5 C realloc() method


“realloc” or “re-allocation” method in C is used to dynamically change the memory allocation
of a previously allocated memory. In other words, if the memory previously allocated with the
help of malloc or calloc is insufficient, realloc can be used to dynamically re-allocate
memory. re-allocation of memory maintains the already present value and new blocks will be
initialized with the default garbage value.

a) Syntax of realloc() in C

ptr = realloc(ptr, newSize);


where ptr is reallocated with new size 'newSize'.
If space is insufficient, allocation fails and returns a NULL pointer.

Example of realloc() in C

#include <stdio.h>
#include <stdlib.h>

int main()
{

// This pointer will hold the


// base address of the block created
int* ptr;
int n, i;

// Get the number of elements for the array


n = 5;
printf("Enter number of elements: %d\n", n);

// Dynamically allocate memory using calloc()


ptr = (int*)calloc(n, sizeof(int));

// Check if the memory has been successfully


// allocated by malloc or not
if (ptr == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {
// Memory has been successfully allocated
printf("Memory successfully allocated using calloc.\n");

// Get the elements of the array


for (i = 0; i < n; ++i) {
ptr[i] = i + 1;
}

// Print the elements of the array


printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}

// Get the new size for the array


n = 10;
printf("\n\nEnter the new size of the array: %d\n", n);

// Dynamically re-allocate memory using realloc()


ptr = (int*)realloc(ptr, n * sizeof(int));

// Memory has been successfully allocated


printf("Memory successfully re-allocated using realloc.\
n");

// Get the new elements of the array


for (i = 5; i < n; ++i) {
ptr[i] = i + 1;
}

// Print the elements of the array


printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}

free(ptr);
}

return 0;
}

Output

Enter number of elements: 5


Memory successfully allocated using calloc.
The elements of the array are: 1, 2, 3, 4, 5,
Enter the new size of the array: 10
Memory successfully re-allocated using realloc.
The elements of the array are: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,

Let us see the differences in a tabular form:

S.No. malloc() calloc()

malloc() is a function that creates calloc() is a function that assigns a


1. one block of memory of a fixed specified number of blocks of memory to
size. a single variable.

2. malloc() only takes one argument calloc() takes two arguments.

3. malloc() is faster than calloc. calloc() is slower than malloc()

4. malloc() has high time efficiency calloc() has low time efficiency

malloc() is used to indicate calloc() is used to indicate contiguous


5.
memory allocation memory allocation

Syntax : void* calloc(size_t num, size_t


6. Syntax : void* malloc(size_t size);
size);

malloc() does not initialize the


8. calloc() initializes the memory to zero
memory to zero

malloc() does not add any extra calloc() adds some extra memory
9.
memory overhead overhead

1.7 Dynamic Array in C

Array in C is static in nature, so its size should be known at compile time and we can’t
change the size of the array after its declaration. Due to this, we may encounter situations
where our array doesn’t have enough space left for required elements or we allotted more
than the required memory leading to memory wastage. To solve this problem, dynamic
arrays come into the picture.
A Dynamic Array is allocated memory at runtime and its size can be changed later in the
program.

We can create a dynamic array in C by using the following methods:

1) Using malloc() Function


2) Using calloc() Function
3) Resizing Array Using realloc() Function
4) Using Variable Length Arrays(VLAs)
5) Using Flexible Array Members

1) Dynamic Array Using malloc() Function

The “malloc” or “memory allocation” method in C is used to dynamically allocate a single


large block of memory with the specified size. It returns a pointer of type void which can be
cast into a pointer of any form. It is defined inside the <stdlib.h> header file.

Syntax:

ptr = (cast-type*) malloc(byte-size);

We can use this function to create a dynamic array of any type by simply allocating a
memory block of some size and then typecasting the returned void pointer to the pointer of
the required type.

Example:

ptr = (int*) malloc(100 * sizeof(int));

In the above example, we have created a dynamic array of type int and size 100 elements.
Note: It is to be noted that if malloc fails to allocate the required memory, it returns the NULL
pointer. So, it is a good practice to check for NULL pointers to see if the memory is
successfully allocated or not.

// C program to create dynamic array using malloc() function

#include <stdio.h>
#include <stdlib.h>

int main()
{

// address of the block created hold by this pointer


int* ptr;
int size;
// Size of the array
printf("Enter size of elements:");
scanf("%d", &size);

// Memory allocates dynamically using malloc()


ptr = (int*)malloc(size * sizeof(int));

// Checking for memory allocation


if (ptr == NULL) {
printf("Memory not allocated.\n");
}
else {

// Memory allocated
printf("Memory successfully allocated using "
"malloc.\n");

// Get the elements of the array


for (int j = 0; j < size; ++j) {
ptr[j] = j + 1;
}

// Print the elements of the array


printf("The elements of the array are: ");
for (int k = 0; k < size; ++k) {
printf("%d, ", ptr[k]);
}
}

return 0;
}

Output:
Enter size of elements:5
Memory successfully allocated using malloc.
The elements of the array are: 1, 2, 3, 4, 5,

2) Dynamic Array Using calloc() Function


The “calloc” or “contiguous allocation” method in C is used to dynamically allocate the
specified number of blocks of memory of the specified type and initialize each block with a
default value of 0.

The process of creating a dynamic array using calloc() is similar to the malloc() method. The
difference is that calloc() takes arguments instead of one as compared to malloc(). Here, we
provide the size of each element and the number of elements required in the dynamic array.
Also, each element in the array is initialized to zero.
Syntax:

ptr = (cast-type*)calloc(n, element-size);

Example:

ptr = (int*) calloc(5, sizeof(float));

In the above example, we have created a dynamic array of type float having five elements.
Let’s take another example to create a dynamic array using the calloc() method.

Example:

// C program to create dynamic array using calloc() function

#include <stdio.h>
#include <stdlib.h>

int main()
{

// address of the block created hold by this pointer


int* ptr;
int size;

// Size of the array


printf("Enter size of elements:");
scanf("%d", &size);

// Memory allocates dynamically using calloc()


ptr = (int*)calloc(size, sizeof(int));

// Checking for memory allocation


if (ptr == NULL) {
printf("Memory not allocated.\n");
}
else {

// Memory allocated
printf("Memory successfully allocated using "
"malloc.\n");

// Get the elements of the array


for (int j = 0; j < size; ++j) {
ptr[j] = j + 1;
}

// Print the elements of the array


printf("The elements of the array are: ");
for (int k = 0; k < size; ++k) {
printf("%d, ", ptr[k]);
}
}

return 0;
}

Output:
Enter size of elements:6
Memory successfully allocated using malloc.
The elements of the array are: 1, 2, 3, 4, 5, 6,

3) Dynamically Resizing Array Using realloc() Function

The “realloc” or “re-allocation” method in C is used to dynamically change the memory


allocation of a previously allocated memory.
Using this function we can create a new array or change the size of an already existing
array.

Syntax:

ptr = realloc(ptr, newSize);

Let’s take an example to understand this properly.

Example:

// C program to resize dynamic array using realloc()


// function

#include <stdio.h>
#include <stdlib.h>

int main()
{

// address of the block created hold by this pointer


int* ptr;
int size = 5;

// Memory allocates dynamically using calloc()


ptr = (int*)calloc(size, sizeof(int));

if (ptr == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {
printf("Memory successfully allocated using "
"calloc.\n");
}

// inserting elements
for (int j = 0; j < size; ++j) {
ptr[j] = j + 1;
}

printf("The elements of the array are: ");


for (int k = 0; k < size; ++k) {
printf("%d, ", ptr[k]);
}

printf("\n");

size = 10;

int *temp = ptr;

// using realloc
ptr = realloc(ptr, size * sizeof(int));
if (!ptr) {
printf("Memory Re-allocation failed.");
ptr = temp;
}
else {
printf("Memory successfully re-allocated using "
"realloc.\n");
}

// inserting new elements


for (int j = 5; j < size; ++j) {
ptr[j] = j + 10;
}

printf("The new elements of the array are: ");


for (int k = 0; k < size; ++k) {
printf("%d, ", ptr[k]);
}
return 0;
}

Output
Memory successfully allocated using calloc.
The elements of the array are: 1, 2, 3, 4, 5,
Memory successfully re-allocated using realloc.
The new elements of the array are: 1, 2, 3, 4, 5, 15, 16, 17, 18,
19,

5) Variable Length Arrays(VLAs)

Variable length arrays or VLAs, are those arrays in which we can determine the size of the
array at the run time. It allocates the memory in the stack and it’s based on the local scope
level.
The size of a variable length array cannot be changed once it is defined and using variable
length array as its found down sides as compared to above methods.

Example:

// C program to demonstrate the use of VLAs

#include <stdio.h>

int main()
{

int n;
printf("Enter the size of the array: ");
scanf("%d", &n);

int arr[n];

printf("Enter elements: ");

for (int i = 0; i < n; ++i) {

scanf("%d", &arr[i]);
}

printf("Elements of VLA of Given Size: ");


for (int i = 0; i < n; ++i) {

printf("%d ", arr[i]);


}

return 0;
}

Output:
Enter the size of the array: 5
Enter elements: 1 2 3 4 5
Elements of VLA of Given Size: 1 2 3 4 5

5) Flexible Array Members

The flexible array members are the array that is defined inside a structure without any
dimension and their size is flexible. This feature was introduced in C99 standard.
We can control the size of a flexible member using malloc() function.

There are a few rules to follow in the case of flexible array members:

● The array inside the structure should preferably be declared as the last member of
the structure and its size is variable(can be changed at runtime).
● The structure must contain at least one more named member in addition to the
flexible array member.

Let’s take the following structure for example

struct student
{
int len;
int
};

Now to allocate memory, we will use malloc() function as shown below.

struct student *s = malloc(sizeof(*s) + 5 * sizeof(int));

// C program to demonstrate the use of Flexible Array Member


#include <stdio.h>
#include <stdlib.h>

// defining struct
typedef struct {
int len;
int arr[];
} fam;
int main()
{
// creating an array member of size 5
fam* fam1
= (fam*)malloc(sizeof(fam*) + 5 * sizeof(int));

// creating an array mebmer of size 10


fam* fam2
= (fam*)malloc(sizeof(fam*) + 10 * sizeof(int));

// inserting elements
for (int i = 0; i < 5; i++) {
fam1->arr[i] = i + 1;
}
for (int i = 0; i < 10; i++) {
fam2->arr[i] = i + 10;
}

// printing elements
printf("Array of Size 5:\n");
for (int i = 0; i < 5; i++) {
printf("%d, ", fam1->arr[i]);
}
printf("\n");

printf("Array of size 10:\n");


for (int i = 0; i < 10; i++) {
printf("%d, ", fam2->arr[i]);
}
return 0;
}

// C program to demonstrate the use of Flexible Array Member

#include <stdio.h>
#include <stdlib.h>

// defining struct
typedef struct {
int len;
int arr[];
} fam;

int main()
{
// creating an array member of size 5
fam* fam1
= (fam*)malloc(sizeof(fam*) + 5 * sizeof(int));

// creating an array mebmer of size 10


fam* fam2
= (fam*)malloc(sizeof(fam*) + 10 * sizeof(int));

// inserting elements
for (int i = 0; i < 5; i++) {

fam1->arr[i] = i + 1;
}
for (int i = 0; i < 10; i++) {
fam2->arr[i] = i + 10;
}

// printing elements
printf("Array of Size 5:\n");
for (int i = 0; i < 5; i++) {
printf("%d, ", fam1->arr[i]);
}
printf("\n");

printf("Array of size 10:\n");


for (int i = 0; i < 10; i++) {
printf("%d, ", fam2->arr[i]);
}
return 0;
}

Output

Array of Size 5:
1, 2, 3, 4, 5,
Array of size 10:
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
chapter

1.1 Preprocessor

Preprocessors are programs that process the source code before compilation. A number of
steps are involved between writing a program and executing a program in C / C++. Let us
have a look at these steps before we actually start learning about Preprocessors.

You can see the intermediate steps in the above diagram. The source code written by
programmers is first stored in a file, let the name be “program.c“. This file is then processed
by preprocessors and an expanded source code file is generated named “program.i”. This
expanded file is compiled by the compiler and an object code file is generated named
“program.obj”. Finally, the linker links this object code file to the object code of the library
functions to generate the executable file “program.exe”.
1.2 Preprocessor Directives in C/C++
Preprocessor programs provide preprocessor directives that tell the compiler to preprocess
the source code before compiling. All of these preprocessor directives begin with a ‘#’ (hash)
symbol. The ‘#’ symbol indicates that whatever statement starts with a ‘#’ will go to the
preprocessor program to get executed. We can place these preprocessor directives
anywhere in our program.
Examples of some preprocessor directives are: #include, #define, #ifndef, etc.
Note: Remember that the # symbol only provides a path to the preprocessor, and a
command such as include is processed by the preprocessor program. For example, #include
will include the code or content of the specified file in your program.

The following table lists all the preprocessor directives in C/C++:

Preprocessor Directives Description

#define Used to define a macro

#undef Used to undefine a macro

#include Used to include a file in the source code program

Used to include a section of code if a certain macro is


#ifdef
defined by #define

Used to include a section of code if a certain macro is not


#ifndef
defined by #define

#if Check for the specified condition

#else Alternate code that executes when #if fails

#endif Used to mark the end of #if, #ifdef, and #ifndef

These preprocessors can be classified based on the type of function they perform.
1.3 Types of C/C++ Preprocessors
There are 4 Main Types of Preprocessor Directives:

1) Macros
2) File Inclusion
3) Conditional Compilation
4) Other directives

Let us now learn about each of these directives in detail.

1) Macros

In C/C++, Macros are pieces of code in a program that is given some name. Whenever this
name is encountered by the compiler, the compiler replaces the name with the actual piece
of code. The ‘#define’ directive is used to define a macro.

a) Syntax of Macro Definition

#define token value

where after preprocessing, the token will be expanded to its value in the program.

Example of a Macro

// C Program to illustrate the macro

#include <stdio.h>

// macro definition
#define LIMIT 5

int main()
{
for (int i = 0; i < LIMIT; i++) {
printf("%d \n", i);
}

return 0;
}

Output
0
1
2
3
4

In the above program, when the compiler executes the word LIMIT, it replaces it with 5. The
word ‘LIMIT’ in the macro definition is called a macro template and ‘5’ is macro expansion.
Note: There is no semi-colon (;) at the end of the macro definition. Macro definitions do not
need a semi-colon to end.
There are also some Predefined Macros in C which are useful in providing various
functionalities to our program.

b) Macros With Arguments

We can also pass arguments to macros. Macros defined with arguments work similarly to
functions.

Example

#define foo(a, b) a + b
#define func(r) r * r

Let us understand this with a program:

// C Program to illustrate function like macros


#include <stdio.h>

// macro with parameter


#define AREA(l, b) (l * b)

int main()
{
int l1 = 10, l2 = 5, area;

area = AREA(l1, l2);

printf("Area of rectangle is: %d", area);

return 0;
}

Output

Area of rectangle is: 50

We can see from the above program that whenever the compiler finds AREA(l, b) in the
program, it replaces it with the statement (l*b). Not only this, but the values passed to the
macro template AREA(l, b) will also be replaced in the statement (l*b). Therefore AREA(10,
5) will be equal to 10*5.
2) File Inclusion
This type of preprocessor directive tells the compiler to include a file in the source code
program. The #include preprocessor directive is used to include the header files in the C/C+
+ program.
There are two types of files that can be included by the user in the program:

a) Standard Header Files

The standard header files contain definitions of pre-defined functions like printf(), scanf(),
etc. These files must be included to work with these functions. Different functions are
declared in different header files.
For example, standard I/O functions are in the ‘iostream’ file whereas functions that perform
string operations are in the ‘string’ file.

Syntax:

#include <file_name>

where file_name is the name of the header file to be included. The ‘<‘ and ‘>’ brackets tell
the compiler to look for the file in the standard directory.

b) User-defined Header Files

When a program becomes very large, it is a good practice to divide it into smaller files and
include them whenever needed. These types of files are user-defined header files. These
files can be included as:

#include "filename"

The double quotes ( ” ” ) tell the


compiler to search for the header file in the source file’s directory.

3) Conditional Compilation
Conditional Compilation in C/C++ directives is a type of directive that helps to compile a
specific portion of the program or to skip the compilation of some specific part of the program
based on some conditions. There are the following preprocessor directives that are used to
insert conditional code:

1. #if Directive
2. #ifdef Directive
3. #ifndef Directive
4. #else Directive
5. #elif Directive
6. #endif Directive
#endif directive is used to close off the #if, #ifdef, and #ifndef opening directives which
means the preprocessing of these directives is completed.

Syntax

#ifdef macro_name
statement1;
statement2;
statement3;
.
.
.
statementN;
#endif

If the macro with the name ‘macro_name‘ is defined, then the block of statements will
execute normally, but if it is not defined, the compiler will simply skip this block of
statements.

4) Other Directives

Apart from the above directives, there are two more directives that are not commonly used.
These are:

1. #undef Directive
2. #pragma Directive

a) #undef Directive

The #undef directive is used to undefine an existing macro. This directive works as:
#undef LIMIT

Using this statement will undefine the existing macro LIMIT. After this statement, every
“#ifdef LIMIT” statement will evaluate as false.

b) #pragma Directive

This directive is a special purpose directive and is used to turn on or off some features.
These types of directives are compiler-specific, i.e., they vary from compiler to compiler.
Some of the #pragma directives are discussed below:

● #pragma startup: These directives help us to specify the functions


that are needed to run before program startup (before the control
passes to main()).
● #pragma exit: These directives help us to specify the functions that
are needed to run just before the program exit (just before the control
returns from main()).

● #pragma warn Directive: This directive is used to hide the warning


message which is displayed during compilation. We can hide the
warnings as shown below:

1. #pragma warn -rvl: This directive hides those warnings which are raised when a
function that is supposed to return a value does not return a value.

2. #pragma warn -par: This directive hides those warnings which are raised when a
function does not use the parameters passed to it.

3. #pragma warn -rch: This directive hides those warnings which are raised when a
code is unreachable. For example, any code written after the return statement in a
function is unreachable.

Note: Below program will not work with GCC compilers.

Example:

// C program to illustrate the #pragma exit and pragma


// startup

#include <stdio.h>

void func1();
void func2();

// specifying funct1 to execute at start


#pragma startup func1
// specifying funct2 to execute before end
#pragma exit func2

void func1() { printf("Inside func1()\n"); }

void func2() { printf("Inside func2()\n"); }

// driver code
int main()
{
void func1();
void func2();
printf("Inside main()\n");
return 0;
}

Output

Inside main()
Expected Output
Inside func1()
Inside main()
Inside func2()

The above code will produce the output as given below when run on GCC compilers:

Inside main()

This happens because GCC does not support #pragma startup or exit. However, you can
use the below code for the expected output on GCC compilers.

#include <stdio.h>

void func1();
void func2();

void __attribute__((constructor)) func1();


void __attribute__((destructor)) func2();

void func1()
{
printf("Inside func1()\n");
}

void func2()
{
printf("Inside func2()\n");
}

int main()
{
printf("Inside main()\n");

return 0;
}

Output

Inside func1()
Inside main()
Inside func2()

In the above program, we have used some specific syntaxes so that one of the functions
executes before the main function and the other executes after the main function.

1.4 Compiling a C program – Behind the Scene

A Preprocessor is a system software (a computer program that is designed to run on


computer’s hardware and application programs). It performs preprocessing of the High Level
Language(HLL). Preprocessing is the first step of the language processing system.
Language processing system translates the high level language to machine level language
or absolute machine code(i.e. to the form that can be understood by machine).

● The preprocessor doesn’t know about the scope rules of C. Preprocessor directives
like #define come into effect as soon as they are seen and remain in effect until the
end of the file that contains them; the program’s block structure is irrelevant.

A Preprocessor mainly performs three tasks on the HLL code :

1. Removing comments : It removes all the comments. A comment is written


only for the humans to understand the code. So, it is obvious that they are of
no use to a machine. So, preprocessor removes all of them as they are not
required in the execution and won’t be executed as well.
This is how to see a file with removed comments in linux) :
Write a C code (let the file name be prog.c). Preprocess it using the command
gcc -E prog.c

You will see the output with the code having no comments.

This file is saved with a ‘.i’ extension (prog.i) which will be input to the
compiler.

2. File inclusion : Including all the files from the library that our program needs.
In HLL we write #include which is a directive for the preprocessor that tells it
to include the contents of the library file specified. For example, #include will
tell the preprocessor to include all the contents in the library file stdio.h.
This can also be written using double quotes – #include “stdio.h”
Note: If the filename is enclosed within angle brackets, the file is searched for
in the standard compiler include paths. If the filename is enclosed within
double quotes, the search path is expanded to include the current source
directory.
3. Macro expansion : Macros can be called as small functions that are not as
overhead to process. If we have to write a function (having a small definition)
that needs to be called recursively (again and again), then we should prefer a
macro over a function.
So, defining these macros is done by a preprocessor.
#define SI 1000
is a simple example of a macro.

There are two types of macros: Object-like (do not take parameters) and function-like (Can
take parameters)

// object-like macro
#define
// function-like macro
● #define ()
You can delete a macro definition with #undef:
// delete the macro
● # undef
● We can write multi-line macro same like function,
but each statement ends with “\”.

#include <stdio.h>

#define MACRO(num, str) {\


printf("%d", num);\
printf(" is");\
printf(" %s number", str);\
printf("\n");\
}

C header files reference

You might also like