C Programming (Bca-203)
C Programming (Bca-203)
BCA 203
SELF LEARNING MATERIAL
DIRECTORATE
OF DISTANCE EDUCATION
1
SLM Module Developed By :
Author:
Reviewed by :
Assessed by:
Study Material Assessment Committee, as per the SVSU ordinance No. VI (2)
DISCLAIMER
No part of this publication which is material protected by this copyright notice may be reproduced
or transmitted or utilized or stored in any form or by any means now known or hereinafter invented,
electronic, digital or mechanical, including photocopying, scanning, recording or by any information
storage or retrieval system, without prior permission from the publisher.
Information contained in this book has been published by Directorate of Distance Education and has
been obtained by its authors from sources be lived to be reliable and are correct to the best of their
knowledge. However, the publisher and its author shall in no event be liable for any errors,
omissions or damages arising out of use of this information and specially disclaim and implied
warranties or merchantability or fitness for any particular use.
2
C PROGRAMMING
UNIT-I
Arrays
Definition, declaration and initialization of one dimensional array; Accessing array
elements; Displaying array elements; Sorting arrays; Arrays and function; Two-
Dimensional array: Declaration and Initialization, Accessing and Displaying, Memory
representation of array [Row Major, Column Major]; Multidimensional array
UNIT-II
Pointers -Definition and declaration, Initialization; Indirection operator, address of
operator; pointer arithmetic; dynamic memory allocation; arrays and pointers; function
and pointers
UNIT-III
Strings
Definition, declaration and initialization of strings; standard library function: strlen(),
strcpy(), strcat(), strcmp(); Implementation without using standard library functions
Structures
Definition and declaration; Variables initialization; Accessing fields and structure
operations; Nested structures; Union: Definition and declaration; Differentiate between
Union and structure
UNIT-IV
Introduction C Preprocessor
Definition of Preprocessor; Macro substitution directives; File inclusion directives;
Conditional compilation
Bitwise Operators
Bitwise operators; Shift operators; Masks; Bit field
UNIT-V
File handling
Definition of Files, Opening modes of files; Standard function: fopen(), fclose(), feof(),
fseek(), fewind();Using text files: fgetc(), fputc(), fscanf() ,Command line arguments
3
UNIT-I
Arrays
Definition
Arrays a kind of data structure that can store a fixed-size sequential collection of
elements of the same type. An array is used to store a collection of data, but it is often
more useful to think of an array as a collection of variables of the same type.
Instead of declaring individual variables, such as number0, number1, ..., and
number99, you declare one array variable such as numbers and use numbers[0],
numbers[1], and ..., numbers[99] to represent individual variables. A specific element in
an array is accessed by an index.
All arrays consist of contiguous memory locations. The lowest address corresponds to
the first element and the highest address to the last element.
Declaring Arrays
To declare an array in C, a programmer specifies the type of the elements and the
number of elements required by an array as follows −
type arrayName [ arraySize ];
This is called a single-dimensional array. The arraySize must be an integer constant
greater than zero and type can be any valid C data type. For example, to declare a 10-
element array called balance of type double, use this statement −
double balance[10];
4
Here balance is a variable array which is sufficient to hold up to 10 double numbers.
Initializing Arrays
You can initialize an array in C either one by one or using a single statement as follows
−
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
The number of values between braces { } cannot be larger than the number of
elements that we declare for the array between square brackets [ ].
If you omit the size of the array, an array just big enough to hold the initialization is
created. Therefore, if you write −
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
You will create exactly the same array as you did in the previous example. Following is
an example to assign a single element of the array −
balance[4] = 50.0;
The above statement assigns the 5th element in the array with a value of 50.0. All
arrays have 0 as the index of their first element which is also called the base index and
the last index of an array will be total size of the array minus 1. Shown below is the
pictorial representation of the array we discussed above –
An element is accessed by indexing the array name. This is done by placing the index
of the element within square brackets after the name of the array. For example −
double salary = balance[9];
5
The above statement will take the 10th element from the array and assign the value to
salary variable. The following example Shows how to use all the three above
mentioned concepts viz. declaration, assignment, and accessing arrays −
#include <stdio.h>
int main () {
return 0;
}
When the above code is compiled and executed, it produces the following result −
Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109
Arrays in Detail
Arrays are important to C and should need a lot more attention. The following important
concepts related to array should be clear to a C programmer −
6
Sr.No. Concept & Description
1 Multi-dimensional arrays
4 Pointer to an array
You can generate a pointer to the first element of an array by simply specifying
the array name, without any index.
The variable allows us to store a single value at a time, what if we want to store roll no.
of 100 students? For this task, we have to declare 100 variables, then assign values to
each of them. What if there are 10000 students or more? As you can see declaring that
many variables for a single entity (i.e student) is not a good idea. In a situation like
these arrays provide a better way to store data.
What is an Array?
An array is a collection of one or more values of the same type. Each value is called an
element of the array. The elements of the array share the same variable name but each
element has its own unique index number (also known as a subscript). An array can be
of any type, For example: int, float, char etc. If an array is of type int then it's elements
must be of type int only.
7
storing 100 values. In C, index or subscript starts from 0, so roll_no[0] is the first
element, roll_no[1] is the second element and so on. Note that the last element of the
array will be at roll_no[99] not at roll_no[100] because the index starts at 0.
One-dimensional array
Conceptually you can think of a one-dimensional array as a row, where elements are
stored one after another.
8
Syntax: datatype array_name[size];
size: Number of elements an array can hold. here are some example of array
declarations:
1 int num[100];
2 float temp[20];
3 char ch[50];
num is an array of type int, which can only store 100 elements of type int.
temp is an array of type float, which can only store 20 elements of type float.
ch is an array of type char, which can only store 50 elements of type char.
1 #define SIZE 10
2
9
3 int main()
4{
5 int size = 10;
6
7 int my_arr1[SIZE]; // ok
8 int my_arr2[size]; // not allowed until C99
9 // ...
10 }
Note: Until C99 standard, we were not allowed to use variables to specify the size of the
array. If you are using a compiler which supports C99 standard, the above code would
compile successfully. However, If you're using an older version of C compiler like Turbo
C++, then you will get an error.
The use of symbolic constants makes the program maintainable, because later if you
want to change the size of the array you need to modify it at once place only i.e in
the #define directive.
int my_arr[5];
Array subscript or index can be any expression that yields an integer value. For
example:
10
1 int i = 0, j = 2;
2 my_arr[i]; // 1st element
3 my_arr[i+1]; // 2nd element
4 my_arr[i+j]; // 3rd element
In the array my_arr, the last element is at my_arr[4], What if you try to access elements
beyond the last valid index of the array?
The following program uses for loop to take input and print elements of a 1-D array.
1 #include<stdio.h>
2
3 int main()
4{
5 int arr[5], i;
6
7 for(i = 0; i < 5; i++)
8 {
9 printf("Enter a[%d]: ", i);
10 scanf("%d", &arr[i]);
11 }
12
13 printf("\nPrinting elements of the array: \n\n");
14
15 for(i = 0; i < 5; i++)
16 {
17 printf("%d ", arr[i]);
18 }
19
20 // signal to operating system program ran fine
11
21 return 0;
22 }
Try it now
Expected Output:
1 Enter a[0]: 11
2 Enter a[1]: 22
3 Enter a[2]: 34
4 Enter a[3]: 4
5 Enter a[4]: 34
6
7 Printing elements of the array:
8
9 11 22 34 4 34
How it works:
In Line 5, we have declared an array of 5 integers and variable i of type int. Then a for
loop is used to enter five elements into an array. In scanf() we have used & operator
(also known as the address of operator) on element arr[i] of an array, just like we had
done with variables of type int, float, char etc. Line 13 prints "Printing elements of the
array" to the console. The second for loop prints all the elements of an array one by
one.
1 #include<stdio.h>
2
3 int main()
4{
5 int arr[5], i, s = 0;
6
7 for(i = 0; i < 5; i++)
8 {
9 printf("Enter a[%d]: ", i);
10 scanf("%d", &arr[i]);
11 }
12
12
13 for(i = 0; i < 5; i++)
14 {
15 s += arr[i];
16 }
17
18 printf("\nSum of elements = %d ", s);
19
20 // signal to operating system program ran fine
21 return 0;
22 }
Try it now
Expected Output:
1 Enter a[0]: 22
2 Enter a[1]: 33
3 Enter a[2]: 56
4 Enter a[3]: 73
5 Enter a[4]: 23
6
7 Sum of elements = 207
How it works: The first for loop asks the user to enter five elements into the array. The
second for loop reads all the elements of an array one by one and accumulate the sum
of all the elements in the variable s. Note that it is necessary to initialize the
variable s to 0, otherwise, we will get the wrong answer because of the garbage value
of s.
Initializing Array
When an array is declared inside a function the elements of the array have garbage
value. If an array is global or static, then its elements are automatically initialized to 0.
We can explicitly initialize elements of an array at the time of declaration using the
following syntax:
13
Syntax: datatype array_name[size] = { val1, val2, val3, ..... valN };
val1, val2 ... are the constants known as initializers. Each value is separated by a
comma(,) and then there is a semi-colon (;) after the closing curly brace (}).
After we have understood what are arrays, how they are to be declared, and its
applications, it is time to understand how to access the elements.
Although, we store similar data items into a group called array which is referenced to by
a single name like marks, temp etc as seen previously, however in order to retrieve and
access the elements we do not have a single operation.
We need to use loops for this purpose. We access the elements by incrementing the
value of the index/subscript. These subscripts are integer values.
int i;
14
}
Copy
RUN
In the above example, we are accessing initially the first element of the array which is at
the 0th index, hence the counter i = 0. Then we assign value to it using the assignment
operator. Similarly, we access and assign value to each element until the last one which
is located at 9th index, hence i<10. Because if we put i<= 10; then what happens is
when i =10; there is no rollno[10] as a part of the array; because the last index is 9 as
array initialises from 0.
A very essential part of arrays is to understand how the compiler knows where
individual elements of array are located in memory. So, let us understand how is it
done.
You will be surprised to know that when we use the array name, we are referring to
nothing but the first byte of the array. Array name corresponds to the address of the first
byte of the array.
The subscripts or index are offset / you can say the distance from the starting location of
the array.
15
Also, all the elements are located in consecutive memory locations. Thus using the
name of array which is the base address and offset, C calculates address of all
elements in run-time.
Here, „a‟ is the array, i is the index of element whose address we are calculating (offset)
, data_type_size refers to the memory blocks reserved for a particular data type ; for
e.g: if your array is of integer type ; each element will occupy 2 bytes. Starting index is
usually 0.
For instance, correlate this calculation to your calculation of age. You just require
today‟s date and the date of birth in order to derive age, right ? So consider your base
address is your DOB and today‟s date is the offset or index. Voila ! It‟s easy to relate to
it now, isn‟t it !
Example:
Answer:
Hence,
data_type_size = 2
16
starting index = 0
i =3
In the next section, we shall see how to initialize, input, and assign values in an array.
This is a simple program to create an array and then to print it's all elements.
Arrays are the special variables that store multiple values under the same name in the
contiguous memory allocation. Elements of the array can be accessed through their
indexes.
Here, 1, 2, 3, 4 and 5 represent the elements of the array. These elements can be
accessed through their corresponding indexes, 1.e., 0, 1, 2, 3 and 4.
Algorithm
o STEP 1: START
o STEP 2: INITIALIZE arr[] = {1, 2, 3, 4, 5}.
o STEP 3: PRINT "Elements of given array:"
o STEP 4: REPEAT STEP 5 for(i=0; i<arr.length; i++)
o STEP 5: PRINT arr[i]
o STEP 6: END
Program:
Output:
Sorting arrays
Example
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort(); // Sorts the elements of fruits
Reversing an Array
Example
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort(); // First sort the elements of fruits
fruits.reverse(); // Then reverse the order of the elements
Numeric Sort
However, if numbers are sorted as strings, "25" is bigger than "100", because "2" is
bigger than "1".
18
Because of this, the sort() method will produce incorrect result when sorting numbers.
The compare function should return a negative, zero, or positive value, depending on
the arguments:
function(a, b){return a - b}
When the sort() function compares two values, it sends the values to the compare
function, and sorts the values according to the returned (negative, zero, positive) value.
If the result is 0 no changes are done with the sort order of the two values.
Example:
The compare function compares all the values in the array, two values at a time (a, b).
When comparing 40 and 100, the sort() method calls the compare function(40, 100).
The function calculates 40 - 100 (a - b), and since the result is negative (-60), the sort
function will sort 40 as a value lower than 100.
You can use this code snippet to experiment with numerically and alphabetically sorting:
<p id="demo"></p>
<script>
var points = [40, 100, 1, 5, 25, 10];
document.getElementById("demo").innerHTML = points;
19
function myFunction1() {
points.sort();
document.getElementById("demo").innerHTML = points;
}
function myFunction2() {
points.sort(function(a, b){return a - b});
document.getElementById("demo").innerHTML = points;
}
</script>
o Because an array is not a single item, the array contents are not passed
"by value" as we are used to with normal variables
20
o When an array is sent into a function, only its starting address is really
sent
o This means the function will always have access to the actual array sent
in
Example function:
Note that:
o The varibale arr acts as the local array name inside the function
o It's usually a good idea to pass in the array size as well, as another
parameter. This helps make a function work for any size array
Remember: When passing an array into a function, the function will have access
to the contents of the original array!
21
What if there are functions that should not alter the array contents?
Put const in front of the array parameter to guarantee that the array contents will
not be changed by the function:
Notice that the const on the variable size is a good idea in this example, too.
Why?
Practice exercises
Try writing the following functions (each takes in one or more arrays as a parameter) for
practice:
A function called Sum that takes in an array of type double and returns the sum
of its elements
A function called Average that takes in an integer array and returns the average
of it's elements (as a double)
A function called Reverse that takes in an array (any type) and reverses its
contents
A function called Sort that takes in an array of integers and sorts its contents in
ascending order
A function called Minimum that takes in an array of type double and returns the
smallest number in the array
22
An array of arrays is known as 2D array. The two dimensional (2D) array in C
programming is also known as matrix. A matrix can be represented as a table of rows
and columns. Before we discuss more about two Dimensional array lets have a look at
the following C program.
For now don‟t worry how to initialize a two dimensional array, we will discuss that part
later. This program demonstrates how to store the elements entered by user in a 2d
array and how to display the elements of a two dimensional array.
#include<stdio.h>
int main(){
/* 2D array declaration*/
int disp[2][3];
/*Counter variables for the loop*/
int i, j;
for(i=0; i<2; i++) {
for(j=0;j<3;j++) {
printf("Enter value for disp[%d][%d]:", i, j);
scanf("%d", &disp[i][j]);
}
}
//Displaying array elements
printf("Two Dimensional array elements:\n");
for(i=0; i<2; i++) {
for(j=0;j<3;j++) {
printf("%d ", disp[i][j]);
if(j==2){
printf("\n");
}
}
}
return 0;
}
Output:
23
Enter value for disp[0][1]:2
Enter value for disp[0][2]:3
Enter value for disp[1][0]:4
Enter value for disp[1][1]:5
Enter value for disp[1][2]:6
Two Dimensional array elements:
123
456
Initialization of 2D Array
There are two ways to initialize a two Dimensional arrays during declaration.
int disp[2][4] = {
{10, 11, 12, 13},
{14, 15, 16, 17}
};
OR
int disp[2][4] = { 10, 11, 12, 13, 14, 15, 16, 17};
Although both the above declarations are valid, I recommend you to use the first
method as it is more readable, because you can visualize the rows and columns of 2d
array in this method.
We already know, when we initialize a normal array (or you can say one dimensional
array) during declaration, we need not to specify the size of it. However that‟s not the
case with 2D array, you must always specify the second dimension even if you are
specifying elements during the declaration. Let‟s understand this with the help of few
examples –
/* Valid declaration*/
int abc[2][2] = {1, 2, 3 ,4 }
/* Valid declaration*/
int abc[][2] = {1, 2, 3 ,4 }
/* Invalid declaration – you must specify second dimension*/
int abc[][] = {1, 2, 3 ,4 }
24
/* Invalid because of the same reason mentioned above*/
int abc[2][] = {1, 2, 3 ,4 }
We can calculate how many elements a two dimensional array can have by using this
formula:
The array arr[n1][n2] can have n1*n2 elements. The array that we have in the example
below is having the dimensions 5 and 4. These dimensions are known as subscripts. So
this array has first subscript value as 5 and second subscript value as 4.
So the array abc[5][4] can have 5*4 = 20 elements.
To store the elements entered by user we are using two for loops, one of them is a
nested loop. The outer loop runs from 0 to the (first subscript -1) and the inner for loops
runs from 0 to the (second subscript -1). This way the the order in which user enters the
elements would be abc[0][0], abc[0][1], abc[0][2]…so on.
#include<stdio.h>
int main(){
/* 2D array declaration*/
int abc[5][4];
/*Counter variables for the loop*/
int i, j;
for(i=0; i<5; i++) {
for(j=0;j<4;j++) {
printf("Enter value for abc[%d][%d]:", i, j);
scanf("%d", &abc[i][j]);
}
}
return 0;
}
In above example, I have a 2D array abc of integer type. Conceptually you can visualize
the above array like this:
25
26
However the actual representation of this array in memory would be something like this:
As we know that the one dimensional array name works as a pointer to the base
element (first element) of the array. However in the case 2D arrays the logic is slightly
different. You can consider a 2D array as collection of several one dimensional arrays.
So abc[0] would have the address of first element of the first row (if we consider the
above diagram number 1).
similarly abc[1] would have the address of the first element of the second row. To
understand it better, lets write a C program –
#include <stdio.h>
int main()
27
{
int abc[5][4] ={
{0,1,2,3},
{4,5,6,7},
{8,9,10,11},
{12,13,14,15},
{16,17,18,19}
};
for (int i=0; i<=4; i++)
{
/* The correct way of displaying an address would be
* printf("%p ",abc[i]); but for the demonstration
* purpose I am displaying the address in int so that
* you can relate the output with the diagram above that
* shows how many bytes an int element uses and how they
* are stored in contiguous memory locations.
*
*/
printf("%d ",abc[i]);
}
return 0;
}
Output:
The addresses shown in the output belongs to the first element of each
row abc[0][0], abc[1][0], abc[2][0], abc[3][0] and abc[4][0].
C variables are names used for storing a data value to locations in memory. The value
stored in the c variables may be changed during program execution.
28
C is a strongly typed language. Every variable must be declared, indicating its data type
before it can be used. The declaration can also involve explicit initialization, giving the
variable a value; a variable that is declared but not explicitly initialized is of uncertain
value (and should be regarded as dangerous until it is initialized). In K&R C,
declarations must precede all other statements, but in modern versions of C, this rule is
relaxed so that you don't have to declare a variable until just before you start using it:
The basic form of a variable declaration is shown here:
The type is one of C's data types like int, chat, double etc.
The identifier is the name of the variable. You can initialize the variable by
specifying an equal sign and a value. Keep in mind
You can initialize the variable by specifying an equal sign and a value. Keep in
mind that the initialization expression must result in a value of the same (or
compatible) type as that specified for the variable.
To declare more than one variable of the specified type, use a comma-separated
list.
Declaration of Variable
Declaration of variable in c can be done using following syntax:
data_type variable_name;
or
data_type variable1, variable2,…,variablen;
where data_type is any valid c data type and variable_name is any valid identifier.
For example,
int a;
float variable;
float a, b;
Initialization of Variable
29
C variables declared can be initialized with the help of assignment operator „=‟.
Syntax
data_type variable_name=constant/literal/expression;
or
variable_name=constant/literal/expression;
Example:
int a=10;
int a=b+c;
a=10;
a=b+c;
Multiple variables can be initialized in a single statement by single value, for example,
a=b=c=d=e=10;
NOTE: C variables must be declared before they are used in the c program. Also, since
c is a case-sensitive programming language, therefore the c variables, abc, Abc and
ABC are all different.
/*
C program to demonstrate Declaration and initialization
C program to demonstrate int data type
*/
#include
void main()
{
int age; // Declaration of variable age
age = 20; // initialization of the variable age
printf("%d \n",age);
30
}
Output
20
Press any key to continue . . .
31
int Variable Declaration and Variable Initialization in one line:
/*
C program to demonstrate Declaration and initialization
C program to demonstrate int data type
*/
#include
32
void main()
{
int age=20; // Declaration and initialization of variable age
printf("%d \n",age);
}
Output
20
Press any key to continue . . .
a=b=c=d=e=10;
/*
C program to demonstrate Declaration and initialization
C program to demonstrate int data type
*/
#include
void main()
{
33
Output
10
10
10
10
10
Press any key to continue . . .
Point To remember
Memory space is not allocated for a variable while declaration. It happens only
on the variable definition.
Type Syntax
34
The array allows us to store multiple data of the same data type under the same
name. What if we need to store multiple data of different data type under the same
name? No problem, C Programming language allows us to create structures which let
us store multiple data belonging to different data types under the same name.
Structures are mostly used for maintaining records like mark sheets with student
details like name, ID number, and marks stored under the same name. Another
example is for maintaining library records with the name of the book, author, book ID,
and subject stored under the same name. This is how data gets stored in a structure:
Table of Contents
35
o 2) Using arrow(->) operator
o Program to store and display the student details using Structure and Arrow operator
Recommended -
To begin with, structures can handle multiple data types that are not possible
in arrays. Arrays can only handle the same type of data. Consider the example stated
above of the students‟ details. We can make use of the array in order to store and
access the name, ID number, and marks but we lose a particular identity relating the
data to only one student. In the case of structures, this is not a problem. We can store
and access the data relating to one student without losing the particular identity even
with an enormous amount of data.
DECLARING A STRUCTURE
We already know that structure falls under user-defined data types. So we define a
new data type using the keyword “struct“. The syntax of the declaration is given below:
2. {
3. datatype1 element1;
4. datatype2 element2;
5. datatype3 element3;
6. };
Now we can define variables that shall contain the elements declared under “struct“.
This is shown below:
2. {
3. datatype1 element1;
4. datatype2 element2;
36
5. datatype3 element3;
6. };
7. struct structure_name variable_declarations;
1. struct student
2. {
3. char name[10];
4. int ID;
5. float marks;
6. };
NOTE:
The declaration of a structure only defines the form of the structure and not
allocates memory for storage. The memory is allocated after defining the
variables. Eg: s1,s2,s3;
If we initialize a structure variable to {0} then all its elements will be initialized with a
value 0. Eg: struct student s1={0};
Structures are declared before any function or variable is defined. For complex
codes, they are put in another file and called in the program as header
files using #include.
37
1) USING DOT(.) OPERATOR
In an array, we use the subscript to access the different members of the array.
In structures, we use the dot operator (.) also known as the member access operator.
This operator is placed between the structure variable name and the structure element
that we need to access. For example: if we need to access the name of the first student
then we call it in the following format: s1.name
1. #include <stdio.h>
2. int main()
3. {
5. {
9. };
10.
38
15. struct student s4={0};//all values initialized as 0
16.
26. return 0;
27. }
Output:-
Details of student1:
Name= Ram
ID= 101
marks= 79.000000
Details of student2:
Name= Mohan
39
ID= 102
marks= 99.000000
Details of student3:
Name= Rohan
ID= 103
marks= 55.000000
Details of student4:
Name=
ID= 0
marks= 0.000000
Another way to access the structure is using the arrow operator ( -> operator). This is
mostly used in case of structure pointers or when we pass the address of a structure to
a function(call by reference). This operator is used in the same way as the dot operator,
i.e., between the structure pointer name and structure element. Here is an example of
how we use an arrow operator (This program only discuss about how to access a value
of a structure using a pointer but if you have to create a structure based on user value
then you have to use memory allocation using malloc or any other related method along
with scanf() to read the values for the declared structure pointer):
1. #include <stdio.h>
2.
40
4. struct student{
5. char name[10];
6. int id;
7. double marks;
8. };
9.
10. void display(struct student *);//declaring the function to display the contents of the
structure address passed to the function
11.
13. {
18.
23.
41
24. return 0;
25. }
26.
29. {
32. }
Output:-
Name= Ram
ID= 101
marks= 79.000000
Name= Mohan
ID= 102
marks= 99.000000
42
Computer hardware does not directly support the concept of multidimensional arrays.
Computer memory is unidimensional, providing memory addresses that start at zero
and increase serially to the highest available location. Multidimensional arrays are
therefore a software concept: software (IDL in this case) maps the elements of a multi-
dimensional array into a contiguous linear span of memory addresses. There are two
ways that such an array can be represented in one-dimensional linear memory. These
two options, which are explained below, are commonly called row major and column
major. All programming languages that support multidimensional arrays must choose
one of these two possibilities. This choice is a fundamental property of the language,
and it affects how programs written in different languages share data with each other.
Before describing the meaning of these terms and IDL’s relationship to them, it is
necessary to understand the conventions used when referring to the dimensions of an
array. For mnemonic reasons, people find it useful to associate higher level meanings
with the dimensions of multi-dimensional data. For example, a 2-D variable containing
measurements of ozone concentration on a uniform grid covering the earth might
associate latitude with the first dimension, and longitude with the second dimension.
Such associations help people understand and reason about their data, but they are not
fundamental properties of the language itself. It is important to realize that no matter
what meaning you attach to the dimensions of an array, IDL is only aware of the number
of dimensions and their size, and does not work directly in terms of these higher order
concepts. Another way of saying this is that arr[d1, d2] addresses the same element of
variable arr no matter what meaning you associate with the two dimensions.
In the IDL world, there are two such conventions that are widely used:
•In image processing, the first dimension of an image array is the column, and the second dimensio
Hence, the dominant convention in IDL documentation is to refer to the first dimension of an array
•In the standard mathematical notation used for linear algebra, the first dimension of an array (or m
opposite of the image processing convention.
In computer science, the way array elements are mapped to memory is always defined
using the mathematical [row, column] notation. Much of the following discussion utilizes
the m x n array shown in the following figure, with m rows and n columns:
Given such a 2-dimensional matrix, there are two ways that such an array can be
represented in 1-dimensional linear memory — either row by row (row major), or
column by column (column major):
•Contiguous First Dimension (Column Major): In this approach, all elements of
43
the first dimension (m in this case) are stored contiguously in memory. The 1-D
linear address of element Ad1, d2 is therefore given by the formula (d2*m + d1). As
you move linearly through the memory of such an array, the first (leftmost)
dimension changes the fastest, with the second dimension (n, in this case)
incrementing every time you come to the end of the first dimension:
Note that the m x n array shown above could be represented with equal accuracy as
having m columns and n rows, as shown in the figure below. This corresponds to the
image-processing [column, row] notation. It’s important to note that while the
representation shown is the transpose of the representation in the figure above, the
44
data stored in the computer memory are identical. Only the two-dimensional
representation, which takes its form from the notational convention used, has changed.
IDL’s choice of column-major array layout reflects its roots as an image processing
language. The fact that the elements of the first dimension are contiguous means that
the elements of each row of an image array (using [column, row] notation, as shown in
the second figure, are contiguous. This is the order expected by most graphics
hardware, providing an efficiency advantage for languages that naturally store data that
way. Also, this ordering minimizes virtual memory overhead, since images are accessed
linearly.
It should be clear that the higher-level meanings associated with array dimensions (row,
column, latitude, longitude, etc.) are nothing more than a human notational device. In
general, you can assign any meaning you wish to the dimensions of an array, and as
long as your use of those dimensions is consistent, you will get the correct answer,
regardless of the order in which IDL chooses to store the actual array elements in
computer memory. Thus, it is usually possible to ignore these issues. There are times
however, when understanding memory layout can be important:
Sharing Data With Other Languages
If binary data written by a row major language is to be input and used by IDL,
transposition of the data is usually required first. Similarly, if IDL is writing binary data for
use by a program written in a row major language, transposition of the data before
writing (or on input by the other program) is often required.
Calling Code Written In Other Languages
When passing IDL data to code written in a row major language via dynamic linking
(CALL_EXTERNAL, LINKIMAGE, DLMs), it is often necessary to transpose the data
before passing it to the called code, and to transpose the results.
Matrix Multiplication
Understanding the difference between the IDL # and ## operators requires an
understanding of array layout. For a discussion of how the ordering of such data relates
to IDL mathematics routines, see Manipulating Arrays.
1-D Subscripting Of Multidimensional Array
IDL allows you to index multidimensional arrays using a single 1-D subscript. For
example, given a two dimensional 5x7 array, ARRAY[2,3] and ARRAY[17] refer to the
same array element. Knowing this requires an understanding of the actual array layout
in memory (d2*m + d1, or 3*5+2, which yields 17).
45
Efficiency
Accessing memory in the wrong order can impose a severe performance penalty if your
data is larger than the physical memory in your computer. Accessing elements of an
array along the contiguous dimension minimizes the amount of memory paging required
by the virtual memory subsystem of your computer hardware, and will therefore be the
most efficient. Accessing memory across the non-contiguous dimension can cause
each such access to occur on a different page of system memory. This forces the virtual
memory subsystem into a cycle in which it must continually force current pages of
memory to disk in order to make room for new pages, each of which is only momentarily
accessed. This inefficient use of virtual memory is commonly known as thrashing.
Multidimensional array
In C/C++, we can define multidimensional arrays in simple words as array of arrays. Data
in multidimensional arrays are stored in tabular form (in row major order).
General form of declaring N-dimensional arrays:
data_type array_name[size1][size2]....[sizeN];
Examples:
46
Two-Dimensional Array
Two – dimensional array is the simplest form of a multidimensional array. We can see a
two – dimensional array as an array of one – dimensional array for easier understanding.
The basic form of declaring a two-dimensional array of size x, y:
Syntax:
data_type array_name[x][y];
data_type: Type of data to be stored. Valid C/C++ data type.
We can declare a two dimensional integer array say „x‟ of size 10,20 as:
int x[10][20];
Elements in two-dimensional arrays are commonly referred by x[i][j] where i is the
row number and „j‟ is the column number.
A two – dimensional array can be seen as a table with „x‟ rows and „y‟ columns
where the row number ranges from 0 to (x-1) and column number ranges from 0 to
(y-1). A two – dimensional array „x‟ with 3 rows and 3 columns is shown below:
Initializing Two – Dimensional Arrays: There are two ways in which a Two-Dimensional
array can be initialized.
First Method:
The above array have 3 rows and 4 columns. The elements in the braces from left to right
are stored in the table also from left to right. The elements will be filled in the array in the
order, first 4 elements from the left in first row, next 4 elements in second row and so on.
Better Method:
This type of initialization make use of nested braces. Each set of inner braces represents
one row. In the above example there are total three rows so there are three sets of inner
braces.
47
Accessing Elements of Two-Dimensional Arrays: Elements in Two-Dimensional
arrays are accessed using the row indexes and column indexes.
Example:
int x[2][1];
The above example represents the element present in third row and second column.
Note: In arrays if size of array is N. Its index will be from 0 to N-1. Therefore, for row index
2 row number is 2+1 = 3.
To output all the elements of a Two-Dimensional array we can use nested for loops. We
will require two for loops. One to traverse the rows and another to traverse columns.
filter_none
edit
play_arrow
brightness_4
// C++ Program to print the elements of a
// Two-Dimensional array
#include<iostream>
int main()
48
{
return 0;
Output:
Element at x[0][0]: 0
Element at x[0][1]: 1
Element at x[1][0]: 2
Element at x[1][1]: 3
Element at x[2][0]: 4
Element at x[2][1]: 5
Three-Dimensional Array
Method 1:
49
Better Method:
int x[2][3][4] =
{
{ {0,1,2,3}, {4,5,6,7}, {8,9,10,11} },
{ {12,13,14,15}, {16,17,18,19}, {20,21,22,23} }
};
edit
play_arrow
brightness_4
// C++ program to print elements of Three-Dimensional
// Array
#include<iostream>
int main()
int x[2][3][2] =
50
};
<< endl;
return 0;
Output:
Element at x[0][0][0] = 0
Element at x[0][0][1] = 1
Element at x[0][1][0] = 2
Element at x[0][1][1] = 3
Element at x[0][2][0] = 4
Element at x[0][2][1] = 5
Element at x[1][0][0] = 6
Element at x[1][0][1] = 7
51
Element at x[1][1][0] = 8
Element at x[1][1][1] = 9
Element at x[1][2][0] = 10
Element at x[1][2][1] = 11
In similar ways, we can create arrays with any number of dimension. However the
complexity also increases as the number of dimension increases.
The most used multidimensional array is the Two-Dimensional Array.
This article is contributed by Harsh Agarwal. If you like GeeksforGeeks and would like to
contribute, you can also write an article using contribute.geeksforgeeks.org or mail your
article to [email protected]. See your article appearing on the
GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Attention reader! Don‟t stop learning now. Get hold of all the important DSA concepts with
the DSA Self Paced Course at a student-friendly price and become industry ready.
52
UNIT-II
Pointers
Definition and declaration
Pointers in C are easy and fun to learn. Some C programming tasks are performed
more easily with pointers, and other tasks, such as dynamic memory allocation, cannot
be performed without using pointers. So it becomes necessary to learn pointers to
become a perfect C programmer. Let's start learning them in simple and easy steps.
As you know, every variable is a memory location and every memory location has its
address defined which can be accessed using ampersand (&) operator, which denotes
an address in memory. Consider the following example, which prints the address of the
variables defined −
#include <stdio.h>
int main () {
int var1;
char var2[10];
return 0;
}
When the above code is compiled and executed, it produces the following result −
Address of var1 variable: bff5a400
Address of var2 variable: bff5a3f6
A pointer is a variable whose value is the address of another variable, i.e., direct
address of the memory location. Like any variable or constant, you must declare a
pointer before using it to store any variable address. The general form of a pointer
variable declaration is −
type *var-name;
53
Here, type is the pointer's base type; it must be a valid C data type and var-name is
the name of the pointer variable. The asterisk * used to declare a pointer is the same
asterisk used for multiplication. However, in this statement the asterisk is being used to
designate a variable as a pointer. Take a look at some of the valid pointer declarations
−
int *ip; /* pointer to an integer */
double *dp; /* pointer to a double */
float *fp; /* pointer to a float */
char *ch /* pointer to a character */
The actual data type of the value of all pointers, whether integer, float, character, or
otherwise, is the same, a long hexadecimal number that represents a memory address.
The only difference between pointers of different data types is the data type of the
variable or constant that the pointer points to.
There are a few important operations, which we will do with the help of pointers very
frequently. (a) We define a pointer variable, (b) assign the address of a variable to a
pointer and (c) finally access the value at the address available in the pointer variable.
This is done by using unary operator * that returns the value of the variable located at
the address specified by its operand. The following example makes use of these
operations −
Live Demo
#include <stdio.h>
int main () {
54
return 0;
}
When the above code is compiled and executed, it produces the following result −
Address of var variable: bffd8b3c
Address stored in ip variable: bffd8b3c
Value of *ip variable: 20
NULL Pointers
It is always a good practice to assign a NULL value to a pointer variable in case you do
not have an exact address to be assigned. This is done at the time of variable
declaration. A pointer that is assigned NULL is called a null pointer.
The NULL pointer is a constant with a value of zero defined in several standard
libraries. Consider the following program −
Live Demo
#include <stdio.h>
int main () {
return 0;
}
When the above code is compiled and executed, it produces the following result −
The value of ptr is 0
In most of the operating systems, programs are not permitted to access memory at
address 0 because that memory is reserved by the operating system. However, the
memory address 0 has special significance; it signals that the pointer is not intended to
point to an accessible memory location. But by convention, if a pointer contains the null
(zero) value, it is assumed to point to nothing.
To check for a null pointer, you can use an 'if' statement as follows −
if(ptr) /* succeeds if p is not null */
if(!ptr) /* succeeds if p is null */
55
Pointers in Detail
Pointers have many but easy concepts and they are very important to C programming.
The following important pointer concepts should be clear to any C programmer −
1 Pointer arithmetic
There are four arithmetic operators that can be used in pointers: ++, --, +, -
2 Array of pointers
You can define arrays to hold a number of pointers.
3 Pointer to pointer
C allows you to have pointer on a pointer and so on.
In this tutorial, we will learn how to declare, initialize and use a pointer. We will also
learn what NULL pointer are and where to use them. Let's start
datatype *pointer_name;
Data type of a pointer must be same as the data type of the variable to which the
pointer variable is pointing. void type pointer works with all data types, but is not often
used.
56
Here are a few examples:
#include<stdio.h>
void main()
int a = 10;
Pointer variable always point to variables of same datatype. Let's have an example to
showcase this:
#include<stdio.h>
void main()
57
float a;
int *ptr;
If you are not sure about which variable's address to assign to a pointer variable while
declaration, it is recommended to assign a NULL value to your pointer variable. A
pointer which is assigned a NULL value is called a NULL pointer.
#include <stdio.h>
int main()
return 0;
#include <stdio.h>
int main()
58
a = 10;
return 0;
#include <stdio.h>
int main()
/*
*/
a = &i;
/*
*/
/*
which is 10
*/
60
printf("Value at the address, which is stored by pointer variable a is %d\n", *a);
return 0;
Initialization
A declaration of an object may provide its initial value through the process known
as initialization.
For each declarator, the initializer, if not omitted, may be one of the following:
= expression (1)
= { initializer-list } (2)
expression (1)
{ initializer-list } (2)
61
in compound literals, which are expressions of the form:
( type ) { initializer-list }
Explanation
The initializer specifies the initial value stored in an object.
Explicit initialization
If an initializer is provided, see
scalar initialization for the initialization of scalar types
Implicit initialization
If an initializer is not provided:
objects with automatic storage duration are initialized to indeterminate values (which
may be trap representations)
Zero initialization
In some cases, an object is zero-initialized if it is not initialized explicitly, that is:
pointers are initialized to null pointer values of their types
all elements of arrays, all members of structs, and the first members of unions are
zero-initialized, recursively, plus all padding bits are initialized to zero
(on platforms where null pointer values and floating zeroes have all-bit-zero
representations, this form of initialization for statics is normally implemented by
62
allocating them in the .bss section of the program image)
Notes
When initializing an object of static or thread-local storage duration,
every expression in the initializer must be a constant expression or string literal.
Initializers cannot be used in declarations of objects of incomplete type, VLAs, and
block-scope objects with linkage.
The initial values of function parameters are established as if by assignment from
the arguments of a function call, rather than by initialization.
If an indeterminate value is used as an argument to any standard library call, the
behavior is undefined. Otherwise, the result of any expression involving
indeterminate values is an indeterminate value (e.g. int n;, n may not compare
equal to itself and it may appear to change its value on subsequent reads)
The term zero initialization is not used in C standard. It is adopted from C++ and
used here for convenience of explanation.
There is no special construct in C corresponding value initialization in C++,
however, = {0} (or (T){0} in compound literals) (since C99) can be used instead, as
C standard does not allow empty structs, empty unions, or arrays of zero length.
Example
#include <stdlib.h>
int a[2]; // initializes a to {0, 0}
int main(void)
{
int i; // initializes i to an indeterminate value
static int j; // initializes j to 0
int k = 1; // initializes k to 1
63
free(ptr);
Indirection operator
An indirection operator, in the context of C#, is an operator used to obtain the value of a
variable to which a pointer points. While a pointer pointing to a variable provides an
indirect access to the value of the variable stored in its memory address, the indirection
operator dereferences the pointer and returns the value of the variable at that memory
location. The indirection operator is a unary operator represented by the symbol (*).
C# allows using pointers only in an unsafe region, which implies that the safety of the
code within that region is not verified by the common language runtime (CLR). In the
unsafe region, the indirection operator is allowed to read and write to a pointer. The
following C# statements illustrate the usage of the indirection operator:
int a = 1, b; // line 1
int *pInt = &a; // line 2
b = *pInt; // line 3
In the first line above, a and b are integer variables and a is assigned a value of 1. In
line 2, the address of a is stored in the integer pointer pInt (line 2). The dereference
operator is used in line 3 to assign the value at the address pointed to by pInt to the
integer variable b.
64
The indirection operator should be used to dereference a valid pointer with an address
aligned to the type it points to, so as to avoid undefined behavior at runtime. It should
not be applied to a void pointer or to an expression that is not of a pointer type, to avoid
compiler errors. However, after casting a void pointer to the right pointer type, the
indirection operator can be used.
When declaring multiple pointers in a single statement, the indirection operator should
be written only once with the underlying type and not repeated for each pointer name.
The indirection operator is distributive in C#, unlike C and C++. When the indirection
operator is applied to a null pointer, it results in an implementation-defined behavior.
Since this operator is used in an unsafe context, the keyword unsafe should be used
before it along with the /unsafe option during compilation.
This definition was written in the context of C#
address of operator
An address-of operator is a mechanism within C++ that returns the memory address of
a variable. These addresses returned by the address-of operator are known as pointers,
because they "point" to the variable in memory.
For example, if the user is trying to locate age 26 within the data, the integer variable
would be named age and it would look like this: int age = 26. Then the address operator
is used to determine the location, or the address, of the data using "&age".
From there, the Hex value of the address can be printed out using "cout << &age".
Integer values need to be output to a long data type. Here the address location would
read "cout << long (&age)".
The address-of operator can only be applied to variables with fundamental, structure,
class, or union types that are declared at the file-scope level, or to subscripted array
65
references. In these expressions, a constant expression that does not include the
address-of operator can be added to or subtracted from the address-of expression.
This definition was written in the context of C++
pointer arithmetic
Pointers variables are also known as address data types because they are used to store
the address of another variable. The address is the memory location that is assigned to
the variable. It doesn‟t store any value.
Hence, there are only a few operations that are allowed to perform on Pointers in C
language. The operations are slightly different from the ones that we generally use for
mathematical calculations. The operations are:
1. Increment/Decrement of a Pointer
Increment/Decrement of a Pointer
For Example:
If an integer pointer that stores address 1000 is incremented, then it will increment by
2(size of an int) and the new address it will points to 1002. While if a float type pointer is
incremented then it will increment by 4(size of a float) and the new address will be 1004.
For Example:
If an integer pointer that stores address 1000 is decremented, then it will decrement by
66
2(size of an int) and the new address it will points to 998. While if a float type pointer is
decremented then it will decrement by 4(size of a float) and the new address will be 996.
Below is the program to illustrate pointer increment/decrement:
// C program to illustrate
// pointer increment/decrement
#include <stdio.h>
// Driver Code
int main()
{
// Integer variable
int N = 4;
// Pointer to an integer
int *ptr1, *ptr2;
// Pointer stores
// the address of N
ptr1 = &N;
ptr2 = &N;
67
ptr1--;
return 0;
}
Output:
Addition
When a pointer is added with a value, the value is first multiplied by the size of data type
and then added to the pointer.
filter_none
edit
play_arrow
brightness_4
// C program to illustrate pointer Addition
#include <stdio.h>
// Driver Code
int main()
{
// Integer variable
int N = 4;
// Pointer to an integer
int *ptr1, *ptr2;
68
// Pointer stores the address of N
ptr1 = &N;
ptr2 = &N;
// Addition of 3 to ptr2
ptr2 = ptr2 + 3;
printf("Pointer ptr2 after Addition: ");
printf("%p \n", ptr2);
return 0;
}
Output:
Subtraction
When a pointer is subtracted with a value, the value is first multiplied by the size of the
data type and then subtracted from the pointer.
Below is the program to illustrate pointer Subtraction:
filter_none
edit
play_arrow
brightness_4
// C program to illustrate pointer Subtraction
#include <stdio.h>
// Driver Code
int main()
{
// Integer variable
int N = 4;
69
// Pointer to an integer
int *ptr1, *ptr2;
// Subtraction of 3 to ptr2
ptr2 = ptr2 - 3;
printf("Pointer ptr2 after Subtraction: ");
printf("%p \n", ptr2);
return 0;
}
Output:
The subtraction of two pointers is possible only when they have the same data type. The
result is generated by calculating the difference between the addresses of the two
pointers and calculating how many bits of data it is according to the pointer data type. The
subtraction of two pointers gives the increments between the two pointers.
For Example:
70
play_arrow
brightness_4
// C program to illustrate Subtraction
// of two pointers
#include <stdio.h>
// Driver Code
int main()
{
int x;
// Integer variable
int N = 4;
// Pointer to an integer
int *ptr1, *ptr2;
// Incrementing ptr2 by 3
ptr2 = ptr2 + 3;
return 0;
}
Output:
71
Pointer Arthemetic on Arrays:
Pointers contain addresses. Adding two addresses makes no sense because there is no
idea what it would point to. Subtracting two addresses lets you compute the offset
between the two addresses. An array name acts like a pointer constant. The value of this
pointer constant is the address of the first element. For Example: if an array named arr
then arr and &arr[0] can be used to reference array as a pointer.
Below is the program to illustrate the Pointer Arithmetic on arrays:
Program 1:
filter_none
edit
play_arrow
brightness_4
// C program to illustrate the array
// traversal using pointers
#include <stdio.h>
// Driver Code
int main()
{
int N = 5;
// An array
int arr[] = { 1, 2, 3, 4, 5 };
72
printf("%d ", ptr[0]);
ptr++;
}
}
Output:
12345
Program 2:
filter_none
edit
play_arrow
brightness_4
// C program to illustrate the array
// traversal using pointers in 2D array
#include <stdio.h>
int i, j;
// Driver Code
73
int main()
{
int N = 3, M = 2;
// A 2D array
int arr[][2] = { { 1, 2 },
{ 3, 4 },
{ 5, 6 } };
// Function Call
traverseArr((int*)arr, N, M);
return 0;
}
Output:
12
34
56
As it can be seen that the length (size) of the array above made 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.
74
This procedure is referred to as Dynamic Memory Allocation in C.
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()
1. C malloc() method
Syntax:
For Example:
75
Example:
filter_none
edit
play_arrow
brightness_4
#include <stdio.h>
#include <stdlib.h>
int main()
int* ptr;
int n, i;
n = 5;
if (ptr == NULL) {
76
printf("Memory not allocated.\n");
exit(0);
else {
ptr[i] = i + 1;
return 0;
Output:
2. C calloc() method
77
“calloc” or “contiguous allocation” method in C is used to dynamically allocate
the specified number of blocks of memory of the specified type. It initializes each
block with a default value „0‟.
Syntax:
For Example:
edit
play_arrow
brightness_4
#include <stdio.h>
#include <stdlib.h>
int main()
int* ptr;
int n, i;
78
// Get the number of elements for the array
n = 5;
if (ptr == NULL) {
exit(0);
else {
ptr[i] = i + 1;
79
printf("The elements of the array are: ");
return 0;
Output:
3. C free() method
Example:
filter_none
edit
play_arrow
brightness_4
#include <stdio.h>
#include <stdlib.h>
80
int main()
int n, i;
n = 5;
exit(0);
else {
81
// Memory has been successfully allocated
free(ptr);
free(ptr1);
return 0;
Output:
82
4. C realloc() method
Syntax:
edit
play_arrow
brightness_4
#include <stdio.h>
#include <stdlib.h>
int main()
int* ptr;
int n, i;
83
// Get the number of elements for the array
n = 5;
if (ptr == NULL) {
exit(0);
else {
ptr[i] = i + 1;
84
printf("The elements of the array are: ");
n = 10;
ptr[i] = i + 1;
85
free(ptr);
return 0;
Output:
Before you learn about the relationship between arrays and pointers, be sure to check
these two topics:
C Arrays
C Pointers
An array is a block of sequential data. Let's write a program to print addresses of array
elements.
#include <stdio.h>
86
int main() {
int x[4];
int i;
return 0;
}
Output
&x[0] = 1450734448
&x[1] = 1450734452
&x[2] = 1450734456
&x[3] = 1450734460
Address of array x: 1450734448
From the above example, it is clear that &x[0] is equivalent to x. And, x[0] is equivalent
to *x.
87
Similarly,
#include <stdio.h>
int main() {
int i, x[6], sum = 0;
printf("Enter 6 numbers: ");
for(i = 0; i < 6; ++i) {
// Equivalent to scanf("%d", &x[i]);
scanf("%d", x+i);
Enter 6 numbers: 2
3
4
4
12
4
Sum = 29
88
Here, we have declared an array x of 6 elements. To access elements of the array, we
have used pointers.
In most contexts, array names decay to pointers. In simple words, array names are
converted to pointers. That's the reason why you can use pointers to access elements
of arrays. However, you should remember that pointers and arrays are not the same.
There are a few cases where array names don't decay to pointers. To learn more,
visit: When does array name doesn't decay into a pointer?
Example 2: Arrays and Pointers
#include <stdio.h>
int main() {
int x[5] = {1, 2, 3, 4, 5};
int* ptr;
return 0;
}
*ptr = 3
*(ptr+1) = 4
*(ptr-1) = 2
In this example, &x[2], the address of the third element, is assigned to the ptr pointer.
Hence, 3 was displayed when we printed *ptr.
And, printing *(ptr+1) gives us the fourth element. Similarly, printing *(ptr-1) gives us the
second element.
89
function and pointers
Pointers give greatly possibilities to 'C' functions which we are limited to return one
value. With pointer parameters, our functions now can process actual data rather than a
copy of data.
In order to modify the actual values of variables, the calling statement passes
addresses to pointer parameters in a function.
Function Pointers
90
*b = temp;}
}
Output:
m is 25, n is 100
m is 100, n is 25
The program swaps the actual variables values because the function accesses them by
address using pointers. Here we will discuss the program process:
1. We declare the function responsible for swapping the two variable values, which
takes two integer pointers as parameters and returns any value when it is called.
2. In the main function, we declare and initialize two integer variables ('m' and 'n')
then we print their values respectively.
3. We call the swap() function by passing the address of the two variables as
arguments using the ampersand symbol. After that, we print the new swapped
values of variables.
4. Here we define the swap() function content which takes two integer variable
addresses as parameters and declare a temporary integer variable used as a
third storage box to save one of the value variables which will be put to the
second variable.
5. Save the content of the first variable pointed by 'a' in the temporary variable.
7. Update the second variable (pointed by b) by the value of the first variable saved
in the temporary variable.
91
int add_array (int *a, int num_elements);
int main() {
int Tab[5] = {100, 220, 37, 16, 98};
printf("Total summation is %d\n", add_array(Tab, 5));
return 0;}
int add_array (int *p, int size) {
int total = 0;
int k;
for (k = 0; k < size; k++) {
total += p[k]; /* it is equivalent to total +=*p ;p++; */}
return (total);}
Output:
2. We declare and initialize an integer array with five integer elements. We print the
total summation by passing the array name (which acts as address) and array
size to the add_array()called function as arguments.
#include <stdio.h>
int * build_array();
int main() {
int *a;
a = build_array(); /* get first 5 even numbers */
for (k = 0; k < 5; k++)
printf("%d\n", a[k]);
92
return 0;}
int * build_array() {
static int Tab[5]={1,2,3,4,5};
return (Tab);}
Output:
1
2
3
4
5
2. We declare an integer pointer which receives the complete array built after the
function is called and we print its contents by iterating the entire five element
array.
Notice that a pointer, not an array, is defined to store the array address returned by the
function. Also notice that when a local variable is being returned from a function, we
have to declare it as static in the function.
Function Pointers
As we know by definition that pointers point to an address in any memory location, they
can also point to at the beginning of executable code as functions in memory.
A pointer to function is declared with the * ,the general statement of its declaration is:
return_type (*function_name)(arguments)
You have to remember that the parentheses around (*function_name) are important
because without them, the compiler will think the function_name is returning a pointer of
return_type.
After defining the function pointer, we have to assign it to a function. For example, the
next program declares an ordinary function, defines a function pointer, assigns the
93
function pointer to the ordinary function and after that calls the function through the
pointer:
#include <stdio.h>
void Hi_function (int times); /* function */
int main() {
void (*function_ptr)(int); /* function pointer Declaration */
function_ptr = Hi_function; /* pointer assignment */
function_ptr (3); /* function call */
return 0;}
void Hi_function (int times) {
int k;
for (k = 0; k < times; k++) printf("Hi\n");}
Output:
Hi
Hi
Hi
2. We define a pointer function (with its special declaration) which takes an integer
parameter and doesn't return anything.
3. We initialize our pointer function with the Hi_function which means that the
pointer points to the Hi_function().
4. Rather than the standard function calling by taping the function name with
arguments, we call only the pointer function by passing the number 3 as
arguments, and that's it!
Keep in mind that the function name points to the beginning address of the executable
code like an array name which points to its first element. Therefore, instructions like
function_ptr = &Hi_function and (*funptr)(3) are correct.
NOTE: It is not important to insert the address operator & and the indirection operator *
during the function assignment and function call.
94
Array of Function Pointers
An array of function pointers can play a switch or an if statement role for making a
decision, as in the next program:
#include <stdio.h>
int sum(int num1, int num2);
int sub(int num1, int num2);
int mult(int num1, int num2);
int div(int num1, int num2);
int main()
{ int x, y, choice, result;
int (*ope[4])(int, int);
ope[0] = sum;
ope[1] = sub;
ope[2] = mult;
ope[3] = div;
printf("Enter two integer numbers: ");
scanf("%d%d", &x, &y);
printf("Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: ");
scanf("%d", &choice);
result = ope[choice](x, y);
printf("%d", result);
return 0;}
1. We declare and define four functions which take two integer arguments and
return an integer value. These functions add, subtract, multiply and divide the two
95
arguments regarding which function is being called by the user.
3. We assign and initialize each array element with the function already declared.
For example, the third element which is the third function pointer will point to
multiplication operation function.
4. We seek operands and type of operation from the user typed with the keyboard.
5. We called the appropriate array element (Function pointer) with arguments, and
we store the result generated by the appropriate function.
The instruction int (*ope[4])(int, int); defines the array of function pointers. Each array
element must have the same parameters and return type.
The statement result = ope[choice](x, y); runs the appropriate function according to the
choice made by the user The two entered integers are the arguments passed to the
function.
Void pointers are used during function declarations. We use a void * return type permits
to return any type. If we assume that our parameters do not change when passing to a
function, we declare it as const.
For example:
#include <stdio.h>
void* cube (const void* num);
int main() {
int x, cube_int;
x = 4;
cube_int = cube (&x);
96
printf("%d cubed is %d\n", x, cube_int);
return 0;}
Result:
4 cubed is 64
1. We define and declare a function that returns an integer value and takes an
address of unchangeable variable without a specific data type. We calculate the
cube value of the content variable (x) pointed by the num pointer, and as it is a
void pointer, we have to type cast it to an integer data type using a specific
notation (* datatype) pointer, and we return the cube value.
2. We declare the operand and the result variable. Also, we initialize our operand
with value "4."
3. We call the cube function by passing the operand address, and we handle the
returning value in the result variable
In the stdlib.h header file, the Quicksort "qsort()" function uses this technique which is
an algorithm dedicated to sort an array.
void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *)
)
97
void *base : void pointer to the array.
int (*compare (const void *, const void *) : function pointer composed of two
arguments and returns 0 when the arguments have the same value, <0 when
arg1 comes before arg2, and >0 when arg1 comes after arg2.
The following program sorts an integers array from small to big number using qsort()
function:
#include <stdio.h>
#include <stdlib.h>
int compare (const void *, const void *);
int main() {
int arr[5] = {52, 14, 50, 48, 13};
int num, width, i;
num = sizeof(arr)/sizeof(arr[0]);
width = sizeof(arr[0]);
qsort((void *)arr, num, width, compare);
for (i = 0; i < 5; i++)
printf("%d ", arr[ i ]);
return 0;}
Result:
13 14 48 50 52
1. We define compare function composed of two arguments and returns 0 when the
arguments have the same value, <0 when arg1 comes before arg2, and >0 when
arg1 comes after arg2.The parameters are a void pointers type casted to the
98
appropriate array data type (integer)
3. We call the qsort function and pass the array name, size, width, and comparison
function defined previously by the user in order to sort our array in ascending
order.The comparison will be performed by taking in each iteration two array
elements until the entire array will be sorted.
4. We print the array elements to be sure that our array is well sorted by iterating
the entire array using for loop.
99
UNIT-III
Strings
Definition
Strings are actually one-dimensional array of characters terminated by a null character
'\0'. Thus a null-terminated string contains the characters that comprise the string
followed by a null.
The following declaration and initialization create a string consisting of the word "Hello".
To hold the null character at the end of the array, the size of the character array
containing the string is one more than the number of characters in the word "Hello."
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
If you follow the rule of array initialization then you can write the above statement as
follows −
char greeting[] = "Hello";
Following is the memory presentation of the above defined string in C/C++ −
Actually, you do not place the null character at the end of a string constant. The C
compiler automatically places the '\0' at the end of the string when it initializes the
array. Let us try to print the above mentioned string –
100
#include <stdio.h>
int main () {
When the above code is compiled and executed, it produces the following result −
Greeting message: Hello
C supports a wide range of functions that manipulate null-terminated strings –
1 strcpy(s1, s2);
Copies string s2 into string s1.
2 strcat(s1, s2);
Concatenates string s2 onto the end of string s1.
3 strlen(s1);
Returns the length of string s1.
4 strcmp(s1, s2);
Returns 0 if s1 and s2 are the same; less than 0 if s1<s2; greater than 0 if s1>s2.
5 strchr(s1, ch);
Returns a pointer to the first occurrence of character ch in string s1.
101
6 strstr(s1, s2);
Returns a pointer to the first occurrence of string s2 in string s1.
#include <stdio.h>
#include <string.h>
int main () {
return 0;
}
When the above code is compiled and executed, it produces the following result −
strcpy( str3, str1) : Hello
strcat( str1, str2): HelloWorld
strlen(str1) : 10
102
A string is basically a character array which terminates with a „\0‟. It can have
alphabets in both cases, digits and special characters. It is like having a group of
characters that forms words or sentences.
The „\0‟ is also known as the null character. It is placed at the end of any character
array or string. For example:
char name={„C‟,‟O‟,‟D‟,‟I‟,‟N‟,‟G‟,‟E‟,‟E‟,‟K‟,‟\0′};
For some declarations, even if the programmer doesn‟t put the „\0‟ at the end of the
character array the compiler will automatically do that. „\0‟ is only one character,
although it might look like two. The ASCII code of „\0‟ is 0 which is not the same
as „0‟ which has an ASCII code of 48. „\0‟ is what distinguishes a string from a normal
character array. The string related functions identify „\0‟ and recognize where a string
ends. The figure shown below shows how a string is stored in a memory:
Note that the memory locations are random and it might differ for different compilers
and systems.
Before starting our operations on strings we need to declare a string. There are two
ways declaring a string. As a character array and as a pointer:
A string can be initialized in many different ways. Here are those ways:
103
1. char name[]={'C','O','D','I','N','G','E','E','K','\0'}; //as an unsized array. This method
requires the user to put a '\0' at the end
Scanf() is used to take inputs from the user.Strings can be taken as input
using scanf() function. The format is given below:
1. char name[10];
2. scanf("%s", name);
As we already know that string might contain blank spaces, one limitation with scanf() is
that it terminates as soon as it encounters a blank space. Example:
Output: String
To avoid this complication we enter the elements of a string like any normal character
array.Do not forget to add „\0‟ at the end of the string. The syntax is given below:
1. char name[20],ch;//declaration
2. int i=0;
3. while(ch!="\n")
4. {
5. ch=getchar();
6. name[i]=ch;
7. i++;
8. }
104
SIMPLE INPUT PROGRAM ON STRING
Here is a simple program on string which takes input from the user and displays the
string:
1. #include <stdio.h>
2. int main()
3. {
5. int i=0;
6. printf("Enter a string:\n");
8. while(ch!='\n')
9. {
10. ch=getchar();
11. name[i]=ch;
12. i++;
13. }
15. i=0;
18. while(name[i]!='\0')
105
19. {
20. printf("%c",name[i]);
21. i++;
22. }
23. return 0;
24. }
Output:-
Enter a string:
106
In order to acknowledge the potency of standard library functions, let us consider a
situation where you want to simply display a statement without the use of standard
output statements, like printf() or puts() or any other inbuilt display functions.
That would probably be a tedious task and an extensive knowledge of programming at
the engineering level would be required to simply display a statement as your program
output.
Standard Library Functions are basically the inbuilt functions in the C compiler that
makes things easy for the programmer.
As we have already discussed, every C program has at least one function, that is,
the main() function. The main() function is also a standard library function in C since it
is inbuilt and conveys a specific meaning to the C compiler.
2. Significance of Standard Library Functions in C
107
2.1 Usability
Standard library functions allow the programmer to use the pre-existing codes available
in the C compiler without the need for the user to define his own code by deriving the
logic to perform certain basic functions.
2.2 Flexibility
We have already discussed in Function in C tutorial that how easy it is to grasp and use
the syntax of functions.
All the standard library functions in C have been tested multiple times in order to
generate the optimal output with maximum efficiency making it reliable to use.
2.5 Time-saving
Instead of writing numerous lines of codes, these functions help the programmer to
save time by simply using the pre-existing functions.
2.6 Portability
Standard library functions are available in the C compiler irrespective of the device you
are working on. These functions connote the same meaning and hence serve the same
purpose regardless of the operating system or programming environment.
3. Header Files in C
In order to access the standard library functions in C, certain header files need to be
included before writing the body of the program.
Don‟t move further, if you are not familiar with the Header Files in C.
Here is a tabular representation of a list of header files associated with some of the
standard library functions in C:
HEADER
MEANING ELUCIDATION
FILE
108
Standard
Used to perform input and output operations
<stdio.h> input-output
like scanf() and printf().
header
109
<setjmp.h> Jump header Used to perform jump functions.
This is the basic header file used in almost every program written in the C language.
It stands for standard input and standard output used to perform input-output functions,
some of which are:
printf()– Used to display output on the screen.
scanf()– To take input from the user.
getchar()– To return characters on the screen.
putchar()– To display output as a single character on the screen.
fgets()– To take a line as an input.
puts()– To display a line as an output.
fopen()– To open a file.
fclose()– To close a file.
Here is a simple program in C that illustrates the use of <stdio.h> to use scanf()
and printf() functions:
#include<stdio.h> // Use of stdio.h header
int main()
char name[30];
char line[30];
return 0;
Code on Screen-
Output-
111
3.2 <string.h>
Functions such as malloc(), calloc(), realloc() and free() can be used while dealing with
dynamic memory allocation of variables.
Let us learn these 4 basic functions before using them in our program.
It should be clear that these functions are used for dynamic memory allocation of
variables, that is in contrast to arrays that allocate memory in a static (fixed) manner.
112
3.3.1 malloc()
malloc() stands for memory allocation. This function is responsible for reserving a
specific block of memory and returns a null pointer during the execution of the program.
Syntax-
pointer_name = (cast_type * ) malloc (no_of_bytes * size_in_bytes_of_cast_type)
For instance,
Here is a code in C which illustrates the use of malloc() function to find the sum
of numbers entered by the user-
#include <stdio.h>
int main()
scanf("%d", &no_of_elements);
if(pointer == NULL)
exit(0);
113
{
return 0;
Code on Screen-
Output-
114
Grab this Samurai Technique to Learn Arrays in C
3.3.2 calloc()
calloc stands for contiguous allocation. It is similar to malloc in all respects except the
fact that it initializes the memory to 0 and has the ability to allocate numerous blocks of
memory before the execution of the program.
Syntax-
pointer_name = (cast_type*) calloc (no_of_bytes, size_of_cast_type);
For instance,
115
Here is a code in C similar to malloc() that illustrates the use of calloc() function
to find the sum of numbers entered by the user:
#include <stdio.h>
int main()
scanf("%d", &no_of_elements);
if(pointer == NULL)
exit(0);
return 0;
116
Code on Screen-
Output-
117
3.3.3 realloc()
realloc stands for reallocation. It is used to change the size of the previously allocated
memory in case the previously allocated memory is insufficient to meet the required
needs of the variable in C.
Syntax-
pointer_name = realloc(pointer_name, new_size);
For instance,
If initially,
118
Then, using realloc
int main()
*pointer = 5;
*(pointer + 1) = 10;
*(new_pointer + 2) = 15;
return 0;
Code on Screen-
119
Output-
120
3.3.4 free()
free is responsible to free the dynamically allocated memory done by malloc(), calloc()
or realloc() to the system.
121
Syntax-
free( pointer_name );
For instance,
free( pointer );
Here is a code in C similar to malloc() that illustrates the use of free() function to
find the sum of numbers entered by the user:
#include <stdio.h>
int main()
scanf("%d", &no_of_elements);
if(pointer == NULL)
exit(0);
122
}
return 0;
Code on Screen-
Output-
123
3.4 <math.h>
124
pow() – This function is used to find the power raised to that number.
fabs() – This function is used to find the absolute value of a number.
log() – This function is used to find the logarithm of a number.
sin() – This function is used to find the sine value of a number.
cos() – This function is used to find the cosine value of a number.
tan() – This function is used to find the tangent value of a number.
Here is a code in C that illustrates the use of some of the basic <math.h>
functions:
#include <stdio.h>
#include <math.h>
int main()
square_root = sqrt(number);
power_result = pow(base,power);
integer_result = fabs(integer);
return 0;
Code on Screen-
125
Output-
126
3.5 <ctype.h>
127
isdigit() – Used to check if the character is a digit or not.
isalnum() – Used to check if the character is alphanumeric or not.
isupper() – Used to check if the character is in uppercase or not
islower() – Used to check if the character is in lowercase or not.
toupper() – Used to convert the character into uppercase.
tolower() – Used to convert the character into lowercase.
iscntrl() – Used to check if the character is a control character or not.
isgraph() – Used to check if the character is a graphic character or not.
isprint() – Used to check if the character is a printable character or not
ispunct() – Used to check if the character is a punctuation mark or not.
isspace() – Used to check if the character is a white-space character or not.
isxdigit() – Used to check if the character is hexadecimal or not.
<ctype.h> is not supported in Linux but it works fairly well in Microsoft Windows.
3.6 <conio.h>
It is used to perform console input and console output operations like clrscr() to
clear the screen and getch() to get the character from the keyboard.
Note: The header file <conio.h> is not supported in Linux. It works fairly well on
Microsoft Windows.
4. Summary
strlen()
The C library function size_t strlen(const char *str) computes the length of the
string str up to, but not including the terminating null character.
Declaration
128
Parameters
Return Value
Example
#include <stdio.h>
#include <string.h>
int main () {
char str[50];
int len;
len = strlen(str);
printf("Length of |%s| is |%d|\n", str, len);
return(0);
}
Let us compile and run the above program that will produce the following result −
Length of |This is tutorialspoint.com| is |26|
strcpy()
The C library function char *strcpy(char *dest, const char *src) copies the string
pointed to, by src to dest.
Declaration
129
Parameters
dest − This is the pointer to the destination array where the content is to be
copied.
src − This is the string to be copied.
Return Value
Example
int main () {
char src[40];
char dest[100];
return(0);
}
Let us compile and run the above program that will produce the following result −
Final copied string : This is tutorialspoint.com
strcat()
The C library function char *strcat(char *dest, const char *src) appends the string
pointed to by src to the end of the string pointed to by dest.
Declaration
130
Following is the declaration for strcat() function.
Parameters
dest − This is pointer to the destination array, which should contain a C string,
and should be large enough to contain the concatenated resulting string.
src − This is the string to be appended. This should not overlap the destination.
Return Value
Example
int main () {
char src[50], dest[50];
strcat(dest, src);
return(0);
}
Let us compile and run the above program that will produce the following result −
Final destination string : |This is destinationThis is source|
strcmp()
131
The C library function int strcmp(const char *str1, const char *str2) compares the
string pointed to, by str1 to the string pointed to by str2.
Declaration
Parameters
Return Value
Example
int main () {
char str1[15];
char str2[15];
int ret;
strcpy(str1, "abcdef");
strcpy(str2, "ABCDEF");
132
if(ret < 0) {
printf("str1 is less than str2");
} else if(ret > 0) {
printf("str2 is less than str1");
} else {
printf("str1 is equal to str2");
}
return(0);
}
Let us compile and run the above program that will produce the following result −
str2 is less than str1
133
for(i=0; str[i]!='\0'; ++i);
printf("\nLength of input string: %d",i);
return 0;
}
Output:
Structures
Definition and declaration
This article will cover a brief on user defined data types in C. C supports various data
types, out which there are few where programmer gets some benefit. User defined data
types are used to create a variable which can contain few many other data types inside
them. One variable containing many other variables, that's what we mean by user
defined data types.
A user will have complete privilege to keep certain combinations of data types as per
the need and call it a new variable itself.
What is structure in C?
134
We can start with structures in this article and following articles will continue on the
other types. Structure uses a keyword struct. A structure can have a declaration like
below
Declaration/Definition of a structure
struct tagname{
char x;
int y;
float z;
};
Above is the definition for the structure, it says the compiler that what variables it will
contain. Now we need to declare an object of that structure. Also in the above we can
think of the tagname as data types names int , char, etc.
Now use the tagname for getting an object, below is the syntax
When we write the above piece of code, compiler would allocate contagious memory
which can accommodate everything this struct has.
Since we have created many variables inside the structure we may want to access them
and do some operations, below are the few examples:
structvariable.x='A';
/* this will write 'A' for the element x of structure structvariable*/
structvaraible.y=20;
structvariable.z=10.20f;
135
Structure pointer - Declaration, Accessing of Structure members
The objects to a structure can also be a pointer same like we can create a pointer of int.
To achieve this which we will need following declaration:
To access the elements inside the structure we should be using the following syntax
Above we have created two objects for the struct tagname. Those two objects have
independent memory allocated for each of them. Both of them can be compared with
the normal declaration of the variables for example:
int a;
int *a;
Structures play very important role in big systems where we need to combine several
data's into a set and need to capture multiples of that set, perform operations and many
more.
A small piece of code will help understand the use of structures better.
#include <stdio.h>
struct tagname {
char Char;
int Int;
float Dec;
};
int main()
{
struct tagname StructObj;
136
struct tagname *ptrStructObj=&StructObj;
StructObj.Char='H';
ptrStructObj->Int=927;
ptrStructObj->Dec=911.0f;
printf("%C\n",StructObj.Char);
printf("%d\n",ptrStructObj->Int);
printf("%f",ptrStructObj->Dec);
printf("\n");
return 0;
}
Output
H
927
911.000000
Variables initialization
C variables are names used for storing a data value to locations in memory. The value
stored in the c variables may be changed during program execution.
Declaration of Variable
data_type variable_name;
or
data_type variable1, variable2,…,variablen;
where data_type is any valid c data type and variable_name is any valid identifier.
For example,
137
1 int a;
2 float variable;
3 float a, b;
Initialization of Variable
C variables declared can be initialized with the help of assignment operator „=‟.
Syntax
data_type variable_name=constant/literal/expression;
or
variable_name=constant/literal/expression;
Example
1 int a=10;
2 int a=b+c;
3 a=10;
4 a=b+c;
Multiple variables can be initialized in a single statement by single value, for example,
a=b=c=d=e=10;
NOTE: C variables must be declared before they are used in the c program. Also, since
c is a case sensitive programming language, therefore the c variables, abc, Abc and
ABC are all different.
Constant Variables
C variables having same or unchanged value during the execution of a program are
called constant variables. A variable can be declared as constant using keyword const.
For example,
138
Now, if we try to change its value, then it is invalid.
Volatile Variables
Those variables that can be changed at any time by some external sources from
outside or same program are called volatile variables.
Any variable in c can be declared as volatile using keyword volatile.
Syntax
volatile data_type variable_name;
NOTE: If the value of a variable in the current program is to be maintained constant and
desired not to be changed by any other external operation, then the variable declaration
will be volatile const d=10;
Lets say we need to store the data of students like student name, age, address, id etc.
One way of doing this would be creating a different variable for each attribute, however
when you need to store the data of multiple students then in that case, you would need
to create these several variables again for each student. This is such a big headache to
store data in this way.
We can solve this problem easily by using structure. We can create a structure that has
members for name, id, address and age and then we can create the variables of this
structure for each student. This may sound confusing, do not worry we will understand
this with the help of example.
We use struct keyword to create a structure in C. The struct keyword is a short form
of structured data type.
struct struct_name {
DataType member1_name;
DataType member2_name;
DataType member3_name;
…
139
};
Here struct_name can be anything of your choice. Members data type can be same or
different. Once we have declared the structure we can use the struct name as a data
type like int, float etc.
First we will see the syntax of creating struct variable, accessing struct members etc
and then we will see a complete example.
struct struct_name {
DataType member1_name;
DataType member2_name;
DataType member3_name;
…
} var_name;
How to access data members of a structure using a struct variable?
var_name.member1_name;
var_name.member2_name;
…
How to assign values to structure members?
var_name.memeber_name = value;
2) All members assigned in one statement
3) Designated initializers – We will discuss this later at the end of this post.
Example of Structure in C
#include <stdio.h>
140
/* Created a structure here. The name of the structure is
* StudentData.
*/
struct StudentData{
char *stu_name;
int stu_id;
int stu_age;
};
int main()
{
/* student is the variable of structure StudentData*/
struct StudentData student;
Output:
You can use a structure inside another structure, which is fairly possible. As I explained
above that once you declared a structure, the struct struct_name acts as a new data
type so you can include it in another struct just like the data type of other data members.
Sounds confusing? Don‟t worry. The following example will clear your doubt.
141
Example of Nested Structure in C Programming
struct stu_address
{
int street;
char *state;
char *city;
char *country;
}
Structure 2: stu_data
struct stu_data
{
int stu_id;
int stu_age;
char *stu_name;
struct stu_address stuAddress;
}
As you can see here that I have nested a structure inside another structure.
Lets take the example of the two structure that we seen above to understand the logic
142
printf("%s", mydata.stuAddress.city);
typedef makes the code short and improves readability. In the above discussion we
have seen that while using structs every time we have to use the lengthy syntax, which
makes the code confusing, lengthy, complex and less readable. The simple solution to
this issue is use of typedef. It is like an alias of struct.
struct home_address {
int local_street;
char *town;
char *my_city;
char *my_country;
};
...
struct home_address var;
var.town = "Agra";
Instead of using the struct home_address every time you need to declare struct
variable, you can simply use addr, the typedef that we have defined.
143
We have already learned two ways to set the values of a struct member, there is
another way to do the same using designated initializers. This is useful when we are
doing assignment of only few members of the structure. In the following example the
structure variable s2 has only one member assignment.
#include <stdio.h>
struct numbers
{
int num1, num2;
};
int main()
{
// Assignment using using designated initialization
struct numbers s1 = {.num2 = 22, .num1 = 11};
struct numbers s2 = {.num2 = 30};
Output:
Nested structures
C provides us the feature of nesting one structure within another structure by using
which, complex data types are created. For example, we may need to store the address
of an entity employee in a structure. The attribute address may also have the subparts
as street number, city, state, and pin code. Hence, to store the address of the
employee, we need to store the address of the employee into a separate structure and
nest the structure address into the structure employee. Consider the following program.
1. #include<stdio.h>
2. struct address
144
3. {
4. char city[20];
5. int pin;
6. char phone[14];
7. };
8. struct employee
9. {
12. };
14. {
20. }
Output
145
Arun
Delhi
110001
1234567890
name: Arun
City: Delhi
Pincode: 110001
Phone: 1234567890
1. By separate structure
2. By Embedded structure
1) Separate structure
Here, we create two structures, but the dependent structure should be used inside the
main structure as a member. Consider the following example.
1. struct Date
2. {
3. int dd;
4. int mm;
5. int yyyy;
6. };
146
7. struct Employee
8. {
9. int id;
12. }emp1;
As you can see, doj (date of joining) is the variable of type Date. Here doj is used as a
member in Employee structure. In this way, we can use Date structure in many
structures.
2) Embedded structure
The embedded structure enables us to declare the structure inside the structure. Hence,
it requires less line of codes but it can not be used in multiple data structures. Consider
the following example.
1. struct Employee
2. {
3. int id;
4. char name[20];
5. struct Date
6. {
7. int dd;
8. int mm;
9. int yyyy;
147
10. }doj;
11. }emp1;
1. e1.doj.dd
2. e1.doj.mm
3. e1.doj.yyyy
1. #include <stdio.h>
2. #include <string.h>
3. struct Employee
4. {
5. int id;
6. char name[20];
7. struct Date
8. {
9. int dd;
148
12. }doj;
13. }e1;
15. {
17. e1.id=101;
19. e1.doj.dd=10;
20. e1.doj.mm=11;
21. e1.doj.yyyy=2014;
22.
27. return 0;
28. }
Output:
employee id : 101
employee name : Sonoo Jaiswal
employee date of joining (dd/mm/yyyy) : 10/11/2014
149
Passing structure to function
Just like other variables, a structure can also be passed to a function. We may pass the
structure members into the function or pass the structure variable at once. Consider the
following example to pass the structure variable employee to a function display() which
is used to display the details of an employee.
1. #include<stdio.h>
2. struct address
3. {
4. char city[20];
5. int pin;
6. char phone[14];
7. };
8. struct employee
9. {
12. };
150
18. scanf("%s %s %d %s",emp.name,emp.add.city, &emp.add.pin, emp.add.phone);
19. display(emp);
20. }
22. {
25. }
Union:
Definition and declaration
Unions can be assumed same as structures but with little difference. Unions can be
used to create a data type containing several others data types inside it and we can use
an object of that union to access the members inside it.
Union declaration
union tagname
{
int a;
char b;
};
Here, union is the keyword to declare a union, tagname is the union name, a and b are
the members of the union tagname.
Now we should create an object for the union in order to access the elements inside it.
Below is how we can do that:
151
union tagname object;
Here, object is the union variable name, that will be used to access the union elements.
object.a= 10;
object.b= 'H';
Till now the union must have looked same as the structures in C. But there is a great
difference between structure and the unions. When we create a structure, the memory
allocated for it is based on the elements inside the structure. So if a structure has two
elements one int and one char than the size of that structure would be at least 5 bytes
(if int takes 4 bytes and 1 byte is for char).
In case of the union the size of memory allocated is equal to the size of the
element which takes largest size.
So for the union above the size would be only 4 bytes not 5 bytes.
union tagname
{
int a;
char s;
char t;
};
152
Size of this object should be 4 bytes only. This feature of unions gives some benefits
but care should be taken while operating with unions. Since the memory allocated is
equal to the largest element in the union, values will be overwritten.
#include<stdio.h>
union tagname
{
int a;
char s;
char t;
};
int main()
{
object.s='H';
object.t='E';
object.a=0xFFFF;
printf("%c\n",object.s);
printf("%c\n",object.t);
printf("%x\n",object.a);
return 0;
}
Output
�
�
ffff
So if the last written element is higher than the size of the previously written elements in
the union, than one might not be able to retrieve the values of the previously written
values.
153
#include<stdio.h>
union tagname
{
int a;
unsigned char s[4];
};
int main()
{
object.a=0xAABBCCDD;
printf("%d\n",sizeof(object));
printf("%X\n",object.a);
char i;
for(i=3;i>=0;i--)
printf("%X\n",object.s[i]);
return 0;
}
Output
4
AABBCCDD
AA
BB
CC
DD
154
Since both Structure and Union can hold different type of data in them but now on the
basis of internal implementation we can find several differences in both of these
containers.
. .
. .
155
Sr. Key Structure Union
No.
156
UNIT-IV
Introduction C Preprocessor
Definition of Preprocessor
The C Preprocessor is not a part of the compiler, but is a separate step in the
compilation process. In simple terms, a C Preprocessor is just a text substitution tool
and it instructs the compiler to do required pre-processing before the actual
compilation. We'll refer to the C Preprocessor as CPP.
All preprocessor commands begin with a hash symbol (#). It must be the first nonblank
character, and for readability, a preprocessor directive should begin in the first column.
The following section lists down all the important preprocessor directives –
1 #define
Substitutes a preprocessor macro.
2
#include
Inserts a particular header from another file.
3 #undef
Undefines a preprocessor macro.
4 #ifdef
Returns true if this macro is defined.
5 #ifndef
Returns true if this macro is not defined.
157
6 #if
Tests if a compile time condition is true.
7 #else
The alternative for #if.
8 #elif
#else and #if in one statement.
9 #endif
Ends preprocessor conditional.
10 #error
Prints error message on stderr.
11 #pragma
Issues special commands to the compiler, using a standardized method.
Preprocessors Examples
#include <stdio.h>
#include "myheader.h"
These directives tell the CPP to get stdio.h from System Libraries and add the text to
the current source file. The next line tells CPP to get myheader.h from the local
directory and add the content to the current source file.
#undef FILE_SIZE
158
#define FILE_SIZE 42
#ifndef MESSAGE
#define MESSAGE "You wish!"
#endif
It tells the CPP to define MESSAGE only if MESSAGE isn't already defined.
#ifdef DEBUG
/* Your debugging statements here */
#endif
It tells the CPP to process the statements enclosed if DEBUG is defined. This is useful
if you pass the -DDEBUG flag to the gcc compiler at the time of compilation. This will
define DEBUG, so you can turn debugging on and off on the fly during compilation.
Predefined Macros
ANSI C defines a number of macros. Although each one is available for use in
programming, the predefined macros should not be directly modified.
1 __DATE__
The current date as a character literal in "MMM DD YYYY" format.
2 __TIME__
The current time as a character literal in "HH:MM:SS" format.
3 __FILE__
This contains the current filename as a string literal.
4 __LINE__
159
This contains the current line number as a decimal constant.
5 __STDC__
Defined as 1 when the compiler complies with the ANSI standard.
Live Demo
#include <stdio.h>
int main() {
When the above code in a file test.c is compiled and executed, it produces the
following result −
File :test.c
Date :Jun 2 2012
Time :03:36:24
Line :8
ANSI :1
Preprocessor Operators
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
160
The Stringize (#) Operator
The stringize or number-sign operator ( '#' ), when used within a macro definition,
converts a macro parameter into a string constant. This operator may be used only in a
macro having a specified argument or parameter list. For example −
Live Demo
#include <stdio.h>
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
int main(void) {
message_for(Carole, Debra);
return 0;
}
When the above code is compiled and executed, it produces the following result −
Carole and Debra: We love you!
Live Demo
#include <stdio.h>
int main(void) {
int token34 = 40;
tokenpaster(34);
return 0;
}
When the above code is compiled and executed, it produces the following result −
token34 = 40
It happened so because this example results in the following actual output from the
preprocessor −
161
printf ("token34 = %d", token34);
This example shows the concatenation of token##n into token34 and here we have
used both stringize and token-pasting.
Live Demo
#include <stdio.h>
int main(void) {
printf("Here is the message: %s\n", MESSAGE);
return 0;
}
When the above code is compiled and executed, it produces the following result −
Here is the message: You wish!
Parameterized Macros
One of the powerful functions of the CPP is the ability to simulate functions using
parameterized macros. For example, we might have some code to square a number as
follows −
int square(int x) {
return x * x;
}
Macros with arguments must be defined using the #define directive before they can be
used. The argument list is enclosed in parentheses and must immediately follow the
162
macro name. Spaces are not allowed between the macro name and open parenthesis.
For example −
Live Demo
#include <stdio.h>
int main(void) {
printf("Max between 20 and 10 is %d\n", MAX(10, 20));
return 0;
}
When the above code is compiled and executed, it produces the following result −
Max between 20 and 10 is 20
Macro substitution
File inclusions
Conditional inclusion/Compilation
operators
163
Rules in writing preprocessor directives
We must follow certain rules while writing preprocessor statement, Some of these rules
are
Every preprocessor statement may be started from the first column (Optional)
Preprocessor statements can be written any where within the block, function or
outside any function
Macro substitution
Macro substitution has a name and replacement text, defined with #define directive. The
preprocessor simply replaces the name of macro with replacement text from the place
where the macro is defined in the source code.
/* Prog.c */
#include<stdio.h>
164
NUM main()
NUM a,b,c;
a=45;
b=25;
c=a+b;
OUT("Sum %d",c);
return 0;
In the above example NUM, OUT are two macros and having their replacement text.
The preprocessor replaces the macro names with their replacement text as
/* Prog.i */
prog.c 4: {
prog.c 6: a=45;
prog.c 7: b=25;
prog.c 8: c=a+b;
165
prog.c 9: printf("Sum %d",c);
prog.c 11: }
2. Macro is not a variable, takes no space; its value can‟t be changes by assigning a
new value
3. The scope of macro is from its point of declaration to the end of source file being
compiled
5. Macro substitution is only done for tokens but not for strings
Constant as macro
Example:
#define PI 3.14
#include<stdio.h>
166
int main()
int rad;
float area,cir;
scanf("%d",&rad);
printf("Area %f",PI*rad*rad);
printf("\nCircumference %f",2*PI*rad);
return 0;
Execution:
Enter the radios: 15
Area 706.500000
Circumference 94.200005
Example explained:
Show Expanded Source
While executing the program PI is replaced with 3.14 by preprocessor in the source
code.
#define PI 3.142857
167
Specification: Accept the current month energy meter reading and previous month
meter reading and print the power bill.
#define C 6.80
#define I 12.50
#define A 0.50
#include<stdio.h>
int main()
int cmr,pmr,nu;
char type;
float bill;
scanf("%c",&type);
scanf("%d",&cmr);
scanf("%d",&pmr);
nu=cmr-pmr;
168
if(type=='d')
bill=nu*D;
else if(type=='c')
bill=nu*C;
else if(type=='i')
bill=nu*I;
else
bill=nu*A;
return 0;
Execution:
The type of connection [domestic/commercial/industrial/agriculture] d/c/i/a: c
Enter the current month meter reading: 500
Enter the previous month meter reading: 200
Number of units consumed: 300
Total bill 2040
Example explained:
Show Expanded Source
If the tariff changes in future then replacement text of macros may be changed without
changing the code in the program.
169
Defining a word as macro
A word can be defined as macro. It is mostly done to improve the readability and
understandability of program.
Example:
#define in scanf
#include<stdio.h>
int main()
int x,y,z;
in("%d%d",&x,&y);
z=x+y;
out("Sum=%d",z);
return 0;
Execution:
Enter two numbers:
6
170
9
Sum=15
Example explained:
Show Expanded Source
The preprocessor replaces “printf” in place of “out” and “scanf” in place of “in” before
compilation of program.
Example:
#define C }
#include<stdio.h>
printf("Hello world");
return 0;
Output:
Hello world
Example explained:
Show Expanded Source
171
Here B is replaced with int main() and C is replaced with } by the preprocessor before
compilation.
Example:
#define B int main()\
#include<stdio.h>
printf("Hello world");
Output:
Hello world
Example explained
Show Expanded Source
By using this pre-processor, we can include a file in another file. Generally, by using this
pre-processor, we are including the Header file. A header file is a source file that
172
contains forward declaration of predefined functions, global variables, constants value,
predefined datatypes, predefined structures, predefined macros, inline functions. .h files
don‟t provide any implementation part of predefined functions; it provides only forward
declaration (prototype). A C program is a combination of predefined and user-defined
functions. .C file contains the implementation part of user-defined functions and calling
statements of predefined functions. If the functions are user-defined or predefined, the
logic part must be required. Project-related .obj files provide the implementation of user-
defined functions, .lib files provides implementation part of pre-defined functions which
is loaded at the time of linking.
As per the function approach, when we are calling a function which is defined later for
avoiding the compilation error, we are required to go for forwarding declaration i.e.
prototype is required. If the function is user-defined, we can provide forward declaration
explicitly but if it is the pre-defined function, we required to use header-file. In C
programming language, .h files provide prototypes of pre-defined function. As a
programmer, it is possible to provide the forward declaration of pre-defined function
explicitly but when we are providing forward declaration then compiler thinks it is a user-
defined function so not recommended. .h files don‟t pass for compilation process but .h
file code is compiled. When we are including any header files at the time of pre-
processing, that header file code will be substituted into current source code and with
current source code header file code also compile.
#include<filename.h>:
By using this syntax, when we are including header file then it will be loaded from
default directory i.e. C:\TC\INCLUDE. Generally, by using this syntax we are including
pre-defined header files. When we are including pre-defined header files. When we are
including user-defined header files by using this syntax then we need to place a user-
defined header file in predefined header directory i.e. C:\TC\INCLUDE.
#include “filename.h”:
By using this syntax, when we are including header, then it is loaded from the current
working directory. Generally, by using this syntax we are including user-defined header
files. By using this syntax, when we are including pre-defined header files then first it will
search in the current project directory if it is not available then loaded from default
directory so it is a time-taking process.
173
Conditional compilation
This C Tutorial explains Conditional Compilation in C programming.
Well! We all know that while debugging the source code of a program, we generally
include printf() statements at several places of doubts to know until where has been
execution going correct, until where have been if the values of required variables
evaluated correctly? These statements we rather would not physically remove from the
source code as the same might be required again while maintenance modifications of
the program. In such situations, conditional compilation
is the perfect! Let‟s consider a simple ex.,
#include <stdio.h>
#define DEBUG printf("value of x = %d and y = %d.\n", x, y)
x++;
y++;
DEBUG;
increase(++x, y++);
DEBUG;
++x;
++y;
DEBUG;
}
Notice that we inserted DEBUG statements at several places to know the modified
values of variables x and y to ascertain the way how are they being evaluated in the
program? But, of course, we wouldn‟t like them to appear in the output once the
evaluation trend is clear. we rather hide them by enclosing in conditional directives as
follows,
174
#if 0
DEBUG;
#endif
Notice the #if construct which had its matching #endif. This is the simplest conditional
compilation construct. Constant exp. zero „0‟ following #if is considered false and
therefore preprocessor deleted the entire #if construct from its output while they are
present in the source code.
#if construct also has optional #elif and #else constructs. There can be used any no. of
#elif constructs. Let‟s consider their syntax first,
#if constan_exp
/* statements */
#elif constant-exp
/* other statements */
#else
/* othet statements */
Notice that constant-exp must be a #defined symbol or literal constant! Variables that
don‟t attain their values until run time are not legal candidates because their values
can‟t be determined at the compile time. Let‟s see another ex.,
#define MOUSE 10
#define CAT 0
#if MOUSE
#include "mouse.h"
#elif CAT
#include "cat.h"
#else
#include "horse.h"
#endif
int main(void)
{
int x = 10;
175
Observe in above program, how conditional compilation directives cause compiler what
fragment of code to compile and what to skip. Also, note that any constant exp. is
evaluated only if all previous ones are false. If none of the constant exp. is true, and
else clause is present, it‟s then executed. Preprocessor simply deletes those claues,
constant exp. for which is false.
Bitwise Operators
The following table lists the Bitwise operators supported by C. Assume variable 'A'
holds 60 and variable 'B' holds 13, then –
& Binary AND Operator copies a bit to the result if it exists in both (A & B) =
operands. 12, i.e.,
0000
1100
^ Binary XOR Operator copies the bit if it is set in one operand but (A ^ B) =
not both. 49, i.e.,
0011
0001
~ (~A ) =
Binary One's Complement Operator is unary and has the effect ~(60),
of 'flipping' bits. i.e,. 1100
0011
176
<< Binary Left Shift Operator. The left operands value is moved left A << 2 =
by the number of bits specified by the right operand. 240 i.e.,
1111
0000
>> Binary Right Shift Operator. The left operands value is moved A >> 2 =
right by the number of bits specified by the right operand. 15 i.e.,
0000
1111
Example
Try the following example to understand all the bitwise operators available in C −
Live Demo
#include <stdio.h>
main() {
c = a | b; /* 61 = 0011 1101 */
printf("Line 2 - Value of c is %d\n", c );
c = a ^ b; /* 49 = 0011 0001 */
printf("Line 3 - Value of c is %d\n", c );
177
When you compile and execute the above program, it produces the following result −
Line 1 - Value of c is 12
Line 2 - Value of c is 61
Line 3 - Value of c is 49
Line 4 - Value of c is -61
Line 5 - Value of c is 240
Line 6 - Value of c is 15
Shift operators
The bitwise shift operators are the right-shift operator (>>), which moves the bits of shift-
expression to the right, and the left-shift operator (<<), which moves the bits of shift-
expression to the left. 1
Syntax
Remarks
Important
The following descriptions and examples are valid on Windows for x86 and x64
architectures. The implementation of left-shift and right-shift operators is significantly
different on Windows for ARM devices. For more information, see the "Shift Operators"
section of the Hello ARM blog post.
Left Shifts
The left-shift operator causes the bits in shift-expression to be shifted to the left by the
number of positions specified by additive-expression. The bit positions that have been
vacated by the shift operation are zero-filled. A left shift is a logical shift (the bits that are
shifted off the end are discarded, including the sign bit). For more information about the
kinds of bitwise shifts, see Bitwise shifts.
The following example shows left-shift operations using unsigned numbers. The
example shows what is happening to the bits by representing the value as a bitset. For
more information, see bitset Class.
C++Copy
#include <iostream>
#include <bitset>
178
using namespace std;
int main() {
unsigned short short1 = 4;
bitset<16> bitset1{short1}; // the bitset representation of 4
cout << bitset1 << endl; // 0b00000000'00000100
If you left-shift a signed number so that the sign bit is affected, the result is undefined.
The following example shows what happens when a 1 bit is left-shifted into the sign bit
position.
C++Copy
#include <iostream>
#include <bitset>
int main() {
short short1 = 16384;
bitset<16> bitset1(short1);
cout << bitset1 << endl; // 0b01000000'00000000
Right Shifts
The right-shift operator causes the bit pattern in shift-expression to be shifted to the
right by the number of positions specified by additive-expression. For unsigned
179
numbers, the bit positions that have been vacated by the shift operation are zero-filled.
For signed numbers, the sign bit is used to fill the vacated bit positions. In other words,
if the number is positive, 0 is used, and if the number is negative, 1 is used.
Important
C++Copy
#include <iostream>
#include <bitset>
int main() {
unsigned short short11 = 1024;
bitset<16> bitset11{short11};
cout << bitset11 << endl; // 0b00000100'00000000
The next example shows right-shift operations with positive signed numbers.
C++Copy
#include <iostream>
#include <bitset>
180
int main() {
short short1 = 1024;
bitset<16> bitset1(short1);
cout << bitset1 << endl; // 0b00000100'00000000
The next example shows right-shift operations with negative signed integers.
C++Copy
#include <iostream>
#include <bitset>
int main() {
short neg1 = -16;
bitset<16> bn1(neg1);
cout << bn1 << endl; // 0b11111111'11110000
181
Shifts and Promotions
The expressions on both sides of a shift operator must be integral types. Integral
promotions are performed according to the rules described in Standard Conversions.
The type of the result is the same as the type of the promoted shift-expression.
C++Copy
#include <iostream>
#include <typeinfo>
int main() {
char char1 = 'a';
Additional Details
C++Copy
#include <iostream>
#include <bitset>
int main() {
unsigned int int1 = 4;
bitset<32> b1{int1};
cout << b1 << endl; // 0b00000000'00000000'00000000'00000100
182
unsigned int int2 = int1 << -3; // C4293: '<<' : shift count negative or too big,
undefined behavior
unsigned int int3 = int1 >> -3; // C4293: '>>' : shift count negative or too big,
undefined behavior
unsigned int int4 = int1 << 32; // C4293: '<<' : shift count negative or too big,
undefined behavior
unsigned int int5 = int1 >> 32; // C4293: '>>' : shift count negative or too big,
undefined behavior
unsigned int int6 = int1 << 0;
bitset<32> b6{int6};
cout << b6 << endl; // 0b00000000'00000000'00000000'00000100 (no change)
}
Footnotes
1
The following is the description of the shift operators in the C++11 ISO specification
(INCITS/ISO/IEC 14882-2011[2012]), sections 5.8.2 and 5.8.3.
The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled.
If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one
more than the maximum value representable in the result type. Otherwise, if E1 has a
signed type and non-negative value, and E1 × 2E2 is representable in the corresponding
unsigned type of the result type, then that value, converted to the result type, is the
resulting value; otherwise, the behavior is undefined.
Masks
Bit strings and bitwise operators are often used to make masks. A mask is a bit string
that "fits over" another bit string and produces a desired result, such as singling out
particular bits from the second bit string, when the two bit strings are operated upon.
This is particularly useful for handling flags; programmers often wish to know whether
one particular flag is set in a bit string, but may not care about the others. For example,
you might create a mask that only allows the flag of interest to have a non-zero value,
then AND that mask with the bit string containing the flag.
Consider the following mask, and two bit strings from which we want to extract the final
bit:
mask = 00000001
value1 = 10011011
value2 = 10011100
183
mask & value1 == 00000001
mask & value2 == 00000000
The zeros in the mask mask off the first seven bits and only let the last bit show
through. (In the case of the first value, the last bit is 1; in the case of the second value,
the last bit is 0.)
Alternatively, masks can be built up by operating on several flags, usually with inclusive
OR:
flag1 = 00000001
flag2 = 00000010
flag3 = 00000100
mask == 00000111
See Opening files at a low level, for a code example that actually uses bitwise OR to
join together several flags.
It should be emphasized that the flag and mask examples are written in pseudo-code,
that is, a means of expressing information that resembles source code, but cannot be
compiled. It is not possible to use binary numbers directly in C.
The following code example shows how bit masks and bit-shifts can be combined. It
accepts a decimal number from the user between 0 and 128, and prints out a binary
number in response.
#include <stdio.h>
#define NUM_OF_BITS 8
args_assigned = 0;
184
input_int = -1;
while ((args_assigned != 1) ||
(input_int < 0) || (input_int > 128))
{
puts ("Please enter an integer from 0 to 128.");
my_string = (char *) malloc (nbytes + 1);
getline (&my_string, &nbytes, stdin);
args_assigned = sscanf (my_string, "%d", &input_int);
if ((args_assigned != 1) ||
(input_int < 0) || (input_int > 128))
puts ("\nInput invalid!");
}
/*
Convert decimal numbers into binary
Keep shifting my_short by one to the left
and test the highest bit. This does
NOT preserve the value of my_short!
*/
printf ("\n");
return 0;
}
Bit field
Suppose your C program contains a number of TRUE/FALSE variables grouped in a
structure called status, as follows −
struct {
unsigned int widthValidated;
unsigned int heightValidated;
} status;
185
This structure requires 8 bytes of memory space but in actual, we are going to store
either 0 or 1 in each of the variables. The C programming language offers a better way
to utilize the memory space in such situations.
If you are using such variables inside a structure then you can define the width of a
variable which tells the C compiler that you are going to use only those number of
bytes. For example, the above structure can be re-written as follows −
struct {
unsigned int widthValidated : 1;
unsigned int heightValidated : 1;
} status;
The above structure requires 4 bytes of memory space for status variable, but only 2
bits will be used to store the values.
If you will use up to 32 variables each one with a width of 1 bit, then also the status
structure will use 4 bytes. However as soon as you have 33 variables, it will allocate
the next slot of the memory and it will start using 8 bytes. Let us check the following
example to understand the concept −
Live Demo
#include <stdio.h>
#include <string.h>
int main( ) {
printf( "Memory size occupied by status1 : %d\n", sizeof(status1));
printf( "Memory size occupied by status2 : %d\n", sizeof(status2));
return 0;
}
When the above code is compiled and executed, it produces the following result −
Memory size occupied by status1 : 8
Memory size occupied by status2 : 4
186
Bit Field Declaration
1 type
An integer type that determines how a bit-field's value is interpreted. The type
may be int, signed int, or unsigned int.
2 member_name
The name of the bit-field.
3 width
The number of bits in the bit-field. The width must be less than or equal to the bit
width of the specified type.
The variables defined with a predefined width are called bit fields. A bit field can hold
more than a single bit; for example, if you need a variable to store a value from 0 to 7,
then you can define a bit field with a width of 3 bits as follows −
struct {
unsigned int age : 3;
} Age;
The above structure definition instructs the C compiler that the age variable is going to
use only 3 bits to store the value. If you try to use more than 3 bits, then it will not allow
you to do so. Let us try the following example −
Live Demo
#include <stdio.h>
#include <string.h>
struct {
unsigned int age : 3;
187
} Age;
int main( ) {
Age.age = 4;
printf( "Sizeof( Age ) : %d\n", sizeof(Age) );
printf( "Age.age : %d\n", Age.age );
Age.age = 7;
printf( "Age.age : %d\n", Age.age );
Age.age = 8;
printf( "Age.age : %d\n", Age.age );
return 0;
}
When the above code is compiled it will compile with a warning and when executed, it
produces the following result −
Sizeof( Age ) : 4
Age.age : 4
Age.age : 7
Age.age : 0
UNIT-V
188
File handling
Definition of Files
File handling in C enables us to create, update, read, and delete the files stored on the
local file system through our C program. The following operations can be performed on
a file.
There are many functions in the C library to open, read, write, search and close the file.
A list of file functions are given below:
189
8 fputw() writes an integer to file
We must open a file before it can be read, write, or update. The fopen() function is used
to open a file. The syntax of the fopen() is given below.
o The file name (string). If the file is stored at some specific location, then we must
mention the path at which the file is stored. For example, a file name can be
like "c://some_folder/some_file.ext".
o The mode in which the file is to be opened. It is a string.
Mode Description
190
a+ opens a text file in read and write mode
1. #include<stdio.h>
2. void main( )
3. {
4. FILE *fp ;
5. char ch ;
6. fp = fopen("file_handle.c","r") ;
7. while ( 1 )
8. {
9. ch = fgetc ( fp ) ;
10. if ( ch == EOF )
11. break ;
12. printf("%c",ch) ;
191
13. }
14. fclose (fp ) ;
15. }
Output
#include;
void main( )
{
FILE *fp; // file pointer
char ch;
fp = fopen("file_handle.c","r");
while ( 1 )
{
ch = fgetc ( fp ); //Each character of the file is read and stored in the character file.
if ( ch == EOF )
break;
printf("%c",ch);
}
fclose (fp );
}
The fclose() function is used to close a file. The file must be closed after performing all
the operations on it. The syntax of fclose() function is given below:
A File can be used to store a large volume of persistent data. Like many other
languages 'C' provides following file management functions,
1. Creation of a file
2. Opening a file
3. Reading a file
4. Writing to a file
5. Closing a file
Following are the most important file management functions available in 'C,'
192
function purpose
193
Writing to a File
o fputc() Function:
o fputs () Function:
o fprintf()Function:
Whenever you want to work with a file, the first step is to create a file. A file is nothing
but space in a memory where data is stored.
FILE *fp;
fp = fopen ("file_name", "mode");
In the above syntax, the file is a data structure which is defined in the standard library.
If the file is not present on the system, then it is created and then opened.
If a file is already present on the system, then it is directly opened using this
function.
Whenever you open or create a file, you have to specify what you are going to do with
the file. A file in 'C' programming can be created or opened for reading/writing purposes.
A mode is used to specify whether you want to open a file for any of the below-given
purposes. Following are the different types of modes in 'C' programming which can be
used while working with a file.
194
w Open a file for writing. If a file is in writing
mode, then a new file is created if a file
doesn't exist at all. If a file is already
present on a system, then all the data
inside the file is truncated, and it is opened
for writing purposes.
In the given syntax, the filename and the mode are specified as strings hence they must
always be enclosed within double quotes.
Example:
#include <stdio.h>
int main() {
FILE *fp;
fp = fopen ("data.txt", "w");
}
Output:
File is created in the same folder where you have saved your code.
You can specify the path where you want to create your file
195
#include <stdio.h>
int main() {
FILE *fp;
fp = fopen ("D://data.txt", "w");
}
One should always close a file whenever the operations on file are over. It means the
contents and links to the file are terminated. This prevents accidental damage to the file.
'C' provides the fclose function to perform file closing operation. The syntax of fclose is
as follows,
fclose (file_pointer);
Example:
FILE *fp;
fp = fopen ("data.txt", "r");
fclose (fp);
The fclose function takes a file pointer as an argument. The file associated with the file
pointer is then closed with the help of fclose function. It returns 0 if close was successful
and EOF (end of file) if there is an error has occurred while file closing.
After closing the file, the same file pointer can also be used with other files.
In 'C' programming, files are automatically close when the program is terminated.
Closing a file manually by writing fclose function is a good programming practice.
Writing to a File
In C, when you write to a file, newline characters '\n' must be explicitly added.
196
The program below shows how to perform writing to a file:
fputc() Function:
#include <stdio.h>
int main() {
int i;
FILE * fptr;
char fn[50];
char str[] = "Guru99 Rocks\n";
fptr = fopen("fputc_test.txt", "w"); // "w" defines "writing mode"
for (i = 0; str[i] != '\n'; i++) {
/* write to file using fputc() function */
fputc(str[i], fptr);
}
fclose(fptr);
return 0;
}
Output:
The above program writes a single character into the fputc_test.txt file until it reaches
the next line symbol "\n" which indicates that the sentence was successfully written. The
process is to take each character of the array and write it into the file.
1. In the above program, we have created and opened a file called fputc_test.txt in
a write mode and declare our string which will be written into the file.
2. We do a character by character write operation using for loop and put each
character in our file until the "\n" character is encountered then the file is closed
using the fclose function.
fputs () Function:
#include <stdio.h>
int main() {
FILE * fp;
fp = fopen("fputs_test.txt", "w+");
fputs("This is Guru99 Tutorial on fputs,", fp);
fputs("We don't need to use for loop\n", fp);
fputs("Easier than fputc function\n", fp);
fclose(fp);
return (0);
}
197
OUTPUT:
1. In the above program, we have created and opened a file called fputs_test.txt in
a write mode.
fprintf()Function:
#include <stdio.h>
int main() {
FILE *fptr;
fptr = fopen("fprintf_test.txt", "w"); // "w" defines "writing mode"
/* write to file */
fprintf(fptr, "Learning C with Guru99\n");
fclose(fptr);
return 0;
}
OUTPUT:
1. In the above program we have created and opened a file called fprintf_test.txt in
a write mode.
There are three different functions dedicated to reading data from a file
fgetc(file_pointer): It returns the next character from the file pointed to by the
file pointer. When the end of the file has been reached, the EOF is sent back.
fgets(buffer, n, file_pointer): It reads n-1 characters from the file and stores the
string in a buffer in which the NULL character '\0' is appended as the last
character.
198
mind that as with scanf, fscanf stops reading a string when space or newline is
encountered.
#include <stdio.h>
int main() {
FILE * file_pointer;
char buffer[30], c;
fclose(file_pointer);
return 0;
}
Result:
----read a line----
Learning C with Guru99
199
Read String4 |Guru99|
----read the entire file----
Learning C with Guru99
1. In the above program, we have opened the file called "fprintf_test.txt" which was
previously written using fprintf() function, and it contains "Learning C with
Guru99" string. We read it using the fgets() function which reads line by line
where the buffer size must be enough to handle the entire line.
2. We reopen the file to reset the pointer file to point at the beginning of the file.
Create various strings variables to handle each word separately. Print the
variables to see their contents. The fscanf() is mainly used to extract and parse
data from a file.
3. Reopen the file to reset the pointer file to point at the beginning of the file. Read
data and print it from the file character by character using getc() function until the
EOF statement is encountered
4. After performing a reading operation file using different variants, we again closed
the file using the fclose function.
These are the simplest file operations. Getc stands for get character, and putc stands
for put character. These two functions are used to handle only a single character at a
time.
#include <stdio.h>
int main() {
FILE * fp;
char c;
printf("File Handling\n");
//open a file
fp = fopen("demo.txt", "w");
//writing operation
while ((c = getchar()) != EOF) {
putc(c, fp);
}
//close file
fclose(fp);
printf("Data Entered:\n");
//reading
200
fp = fopen("demo.txt", "r");
while ((c = getc(fp)) != EOF) {
printf("%c", c);
}
fclose(fp);
return 0;
}
Output:
1. In the above program we have created and opened a file called demo in a write
mode.
2. After a write operation is performed, then the file is closed using the fclose
function.
3. We have again opened a file which now contains data in a reading mode. A while
loop will execute until the eof is found. Once the end of file is found the operation
will be terminated and data will be displayed using printf function.
4. After performing a reading operation file is again closed using the fclose function.
Standard function
In this tutorial, you'll learn about the standard library functions in C. More specifically,
what are they, different library functions in C and how to use them in your program.
The prototype and data definitions of these functions are present in their respective
header files. To use these functions we need to include the header file in our program.
For example,
If you want to use the printf() function, the header file <stdio.h> should be included.
#include <stdio.h>
int main()
201
If you try to use printf() without including the stdio.h header file, you will get an error.
1. They work
One of the most important reasons you should use library functions is simply because
they work. These functions have gone through multiple rigorous testing and are easy to
use.
Since, the functions are "standard library" functions, a dedicated group of developers
constantly make them better. In the process, they are able to create the most efficient
code optimized for maximum performance.
Since the general functions like printing to a screen, calculating the square root, and
many more are already written. You shouldn't worry about creating them once again.
With ever-changing real-world needs, your application is expected to work every time,
everywhere. And, these library functions help you in that they do the same thing on
every computer.
To can compute the square root of a number, you can use the sqrt() library function.
The function is defined in the math.h header file.
#include <stdio.h>
#include <math.h>
int main()
scanf("%f", &num);
202
// Computes the square root of num and stores in root.
root = sqrt(num);
return 0;
Enter a number: 12
C Header Files
203
C Header Files
fopen()
The C library function FILE *fopen(const char *filename, const char *mode) opens
the filename pointed to, by filename using the given mode.
Declaration
Parameters
filename − This is the C string containing the name of the file to be opened.
mode − This is the C string containing a file access mode. It includes −
1 "r"
Opens a file for reading. The file must exist.
2 "w"
Creates an empty file for writing. If a file with the same name already exists, its
content is erased and the file is considered as a new empty file.
204
3 "a"
Appends to a file. Writing operations, append data at the end of the file. The file
is created if it does not exist.
4 "r+"
Opens a file to update both reading and writing. The file must exist.
5 "w+"
Creates an empty file for both reading and writing.
6 "a+"
Opens a file for reading and appending.
Return Value
This function returns a FILE pointer. Otherwise, NULL is returned and the global
variable errno is set to indicate the error.
Example
int main () {
FILE * fp;
fclose(fp);
return(0);
}
Let us compile and run the above program that will create a file file.txt with the
following content −
We are in 2012
205
Now let us see the content of the above file using the following program −
#include <stdio.h>
int main () {
FILE *fp;
int c;
fp = fopen("file.txt","r");
while(1) {
c = fgetc(fp);
if( feof(fp) ) {
break ;
}
printf("%c", c);
}
fclose(fp);
return(0);
}
Let us compile and run the above program to produce the following result −
We are in 2012
fclose()
The C library function int fclose(FILE *stream) closes the stream. All buffers are
flushed.
Declaration
Parameters
stream − This is the pointer to a FILE object that specifies the stream to be
closed.
Return Value
This method returns zero if the stream is successfully closed. On failure, EOF is
returned.
206
Example
int main () {
FILE *fp;
fp = fopen("file.txt", "w");
return(0);
}
Let us compile and run the above program that will create a file file.txt, and then it will
write following text line and finally it will close the file using fclose() function.
feof()
The C library function int feof(FILE *stream) tests the end-of-file indicator for the given
stream.
Declaration
Parameters
stream − This is the pointer to a FILE object that identifies the stream.
Return Value
This function returns a non-zero value when End-of-File indicator associated with the
stream is set, else zero is returned.
Example
int main () {
FILE *fp;
207
int c;
fp = fopen("file.txt","r");
if(fp == NULL) {
perror("Error in opening file");
return(-1);
}
while(1) {
c = fgetc(fp);
if( feof(fp) ) {
break ;
}
printf("%c", c);
}
fclose(fp);
return(0);
}
fseek()
The C library function int fseek(FILE *stream, long int offset, int whence) sets the file
position of the stream to the given offset.
Declaration
Parameters
stream − This is the pointer to a FILE object that identifies the stream.
offset − This is the number of bytes to offset from whence.
whence − This is the position from where offset is added. It is specified by one of
the following constants –
1 SEEK_SET
208
Beginning of file
2 SEEK_CUR
Current position of the file pointer
3 SEEK_END
End of file
Return Value
Example
int main () {
FILE *fp;
fp = fopen("file.txt","w+");
fputs("This is tutorialspoint.com", fp);
return(0);
}
Let us compile and run the above program that will create a file file.txt with the
following content. Initially program creates the file and writes This is
tutorialspoint.com but later we had reset the write pointer at 7th position from the
beginning and used puts() statement which over-write the file with the following content
−
This is C Programming Language
Now let's see the content of the above file using the following program −
#include <stdio.h>
int main () {
209
FILE *fp;
int c;
fp = fopen("file.txt","r");
while(1) {
c = fgetc(fp);
if( feof(fp) ) {
break;
}
printf("%c", c);
}
fclose(fp);
return(0);
}
Let us compile and run the above program to produce the following result −
This is C Programming Language
rewind()
The C library function void rewind(FILE *stream) sets the file position to the beginning
of the file of the given stream.
Declaration
Parameters
stream − This is the pointer to a FILE object that identifies the stream.
Return Value
Example
#include <stdio.h>
210
int main () {
char str[] = "This is tutorialspoint.com";
FILE *fp;
int ch;
}
fclose(fp);
return(0);
}
Let us assume we have a text file file.txt that have the following content −
This is tutorialspoint.com
Now let us compile and run the above program to produce the following result −
This is tutorialspoint.com
211
The C library function int fgetc(FILE *stream) gets the next character (an unsigned
char) from the specified stream and advances the position indicator for the stream.
Declaration
Parameters
stream − This is the pointer to a FILE object that identifies the stream on which
the operation is to be performed.
Return Value
This function returns the character read as an unsigned char cast to an int or EOF on
end of file or error.
Example
int main () {
FILE *fp;
int c;
int n = 0;
fp = fopen("file.txt","r");
if(fp == NULL) {
perror("Error in opening file");
return(-1);
} do {
c = fgetc(fp);
if( feof(fp) ) {
break ;
}
printf("%c", c);
} while(1);
fclose(fp);
return(0);
}
212
Let us assume, we have a text file file.txt, which has the following content. This file will
be used as an input for our example program −
We are in 2012
Now, let us compile and run the above program that will produce the following result −
We are in 2012
fputc()
The C library function int fputc(int char, FILE *stream) writes a character (an unsigned
char) specified by the argument char to the specified stream and advances the position
indicator for the stream.
Declaration
Parameters
char − This is the character to be written. This is passed as its int promotion.
stream − This is the pointer to a FILE object that identifies the stream where the
character is to be written.
Return Value
If there are no errors, the same character that has been written is returned. If an error
occurs, EOF is returned and the error indicator is set.
Example
int main () {
FILE *fp;
int ch;
fp = fopen("file.txt", "w+");
for( ch = 33 ; ch <= 100; ch++ ) {
fputc(ch, fp);
}
213
fclose(fp);
return(0);
}
Let us compile and run the above program that will create a file file.txt in the current
directory, which will have following content −
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd
Now let's see the content of the above file using the following program −
#include <stdio.h>
int main () {
FILE *fp;
int c;
fp = fopen("file.txt","r");
while(1) {
c = fgetc(fp);
if( feof(fp) ) {
break ;
}
printf("%c", c);
}
fclose(fp);
return(0);
}
Let us compile and run above program to produce the following result −
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd
fscanf()
The C library function int fscanf(FILE *stream, const char *format, ...) reads
formatted input from a stream.
Declaration
Parameters
stream − This is the pointer to a FILE object that identifies the stream.
214
format − This is the C string that contains one or more of the following items
− Whitespace character, Non-whitespace character and Format specifiers. A
format specifier will be as [=%[*][width][modifiers]type=], which is explained
below −
1 *
This is an optional starting asterisk indicates that the data is to be read from the
stream but ignored, i.e. it is not stored in the corresponding argument.
2 width
This specifies the maximum number of characters to be read in the current
reading operation.
3 modifiers
Specifies a size different from int (in the case of d, i and n), unsigned int (in the
case of o, u and x) or float (in the case of e, f and g) for the data pointed by the
corresponding additional argument: h : short int (for d, i and n), or unsigned short
int (for o, u and x) l : long int (for d, i and n), or unsigned long int (for o, u and x),
or double (for e, f and g) L : long double (for e, f and g)
4 type
A character specifying the type of data to be read and how it is expected to be
read. See next table.
c Single character: Reads the next character. If a width different from char *
1 is specified, the function reads width characters and stores them
in the successive locations of the array passed as argument. No
null character is appended at the end.
215
d Decimal integer: Number optionally preceded with a + or - sign int *
Return Value
This function returns the number of input items successfully matched and assigned,
which can be fewer than provided for, or even zero in the event of an early matching
failure.
Example
#include <stdio.h>
#include <stdlib.h>
216
int main () {
char str1[10], str2[10], str3[10];
int year;
FILE * fp;
rewind(fp);
fscanf(fp, "%s %s %s %d", str1, str2, str3, &year);
fclose(fp);
return(0);
}
Let us compile and run the above program that will produce the following result −
Read String1 |We|
Read String2 |are|
Read String3 |in|
Read Integer |2012|
if( argc == 2 ) {
217
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
}
When the above code is compiled and executed with single argument, it produces the
following result.
$./a.out testing
The argument supplied is testing
When the above code is compiled and executed with a two arguments, it produces the
following result.
$./a.out testing1 testing2
Too many arguments supplied.
When the above code is compiled and executed without passing any argument, it
produces the following result.
$./a.out
One argument expected
It should be noted that argv[0] holds the name of the program itself and argv[1] is a
pointer to the first command line argument supplied, and *argv[n] is the last argument.
If no arguments are supplied, argc will be one, and if you pass one argument
then argc is set at 2.
You pass all the command line arguments separated by a space, but if argument itself
has a space then you can pass such arguments by putting them inside double quotes
"" or single quotes ''. Let us re-write above example once again where we will print
program name and we also pass a command line argument by putting inside double
quotes −
#include <stdio.h>
if( argc == 2 ) {
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 ) {
218
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
}
When the above code is compiled and executed with a single argument separated by
space but inside double quotes, it produces the following result.
$./a.out "testing1 testing2"
219