3_Advanced Concepts of C Programming
3_Advanced Concepts of C Programming
Note:
This material is for introductory reading. You may refer text book for more detail part.
Be prepared with Lab work (Programs). It is practical example of each topic from syllabus.
C Pointers:
A pointer is a derived data type in C. It is built from the one of the fundamental data types available in the
C. Pointer contain memory address as their values. Memory addresses are the locations in computer
memory where program instructions and data are stored. So, we can use pointers to access and manipulate
data stored in memory.
There are 2 important operators that we will use in pointers concepts i.e.
Dereferencing operator (*) used to declare pointer variable and access the value stored in the
address.
Address operator (&) used to returns the address of a variable or to access the address of a
variable to a pointer.
BENEFITS OF POINTERS:
2. Pointers can be used to return multiple values from a function through function arguments.
3. Pointers allow references to functions. So we can pass function as argument to other function.
4. We can save data storage space in memory by using pointer arrays to character strings.
6. Pointer is an efficient tool to manipulate dynamic data structure such as structures, linked lists, queues,
stacks and trees.
Important Points:
Printing a pointer with %d format specifier may result in a warning or undefined behavior
because the size of a pointer (usually 4 or 8 bytes) may not match that of an integer.
Note: 8 bytes for a 64-bit System 4 bytes for a 32-bit System.
The memory address format will always be in hexadecimal format (starting with 0x).
C does not use the term “reference” explicitly (unlike C++), “referencing” in C usually refers to
obtaining the address of a variable using the address operator (&).
Pointers are essential for dynamic memory allocation, providing control over memory usage with
functions like malloc, calloc, and free.
Pointer Declaration:
To declare a pointer, use the dereferencing operator (*) followed by the data type.
Syntax:
type *var-name;
Pointer Initialization:
After declaring a pointer variable, you need to initialize it with the address of another variable using
the address of (&) operator. This process is known as referencing a pointer.
Syntax:
Example:
#include <stdio.h>
int main() {
return 0; }
Pointer Arithmetic in C:
Pointer Arithmetic is the set of valid arithmetic operations that can be performed on pointers.
The pointer variables store the memory address of another variable. It doesn‟t store any value.
1. Increment/Decrement of a Pointer
5. Comparison of pointers
1. Increment/Decrement of a Pointer:
Increment: It is a condition that also comes under addition. When a pointer is incremented, it actually
increments by the number equal to the size of the data type for which it is a pointer.
For Example:
If an integer pointer that stores address 1000 is incremented, then it will increment by 4(size of an int),
and the new address will point to 1004. 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.
#include <stdio.h>
int main(){
int x = 10;
int *y = &x;
y++;
}
Decrement: It is a condition that also comes under subtraction. When a pointer is decremented, it actually
decrements by the number equal to the size of the data type for which it is a pointer.
For Example:
If an integer pointer that stores address 1000 is decremented, then it will decrement by 4(size of an int),
and the new address will point to 996. 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.
Note: It is assumed here that the architecture is 64-bit and all the data types are sized accordingly. For
example, integer is of 4 bytes.
When a pointer is added with an integer value, the value is first multiplied by the size of the data type and
then added to the pointer.
new_address = current_address + i * size_of(data type)
For Example:
Consider the same example as above where the ptr is an integer pointer that stores 1000 as an address. If
we add integer 5 to it using the expression, ptr = ptr + 5, then, the final address stored in the ptr will
be ptr = 1000 + sizeof(int) * 5 = 1020.
#include <stdio.h>
int main(){
int x = 10;
int *y = &x;
y = y+ 4;
When a pointer is subtracted with an integer value, the value is first multiplied by the size of the data type
and then subtracted from the pointer similar to addition.
For Example:
Consider the same example as above where the ptr is an integer pointer that stores 1000 as an address. If
we subtract integer 5 from it using the expression, ptr = ptr – 5, then, the final address stored in the ptr
will be ptr = 1000 – sizeof(int) * 5 = 980.
#include <stdio.h>
int main(){
int x = 10;
int *y = &x;
y = y -2;
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.
Example:
#include <stdio.h>
int main(){
return 0;
5. Comparison of Pointers:
We can compare the two pointers by using the comparison operators in C. We can implement this by
using all operators in C >, >=, <, <=, ==, !=. It returns true for the valid condition and returns false for
the unsatisfied condition.
1. Step 1: Initialize the integer values and point these integer values to the pointer.
2. Step 2: Now, check the condition by using comparison or relational operators on pointer
variables.
#include <stdio.h>
int main()
// declaring array
int arr[5];
if (ptr1 == ptr2) {
else {
return 0;
}
Output:
There are various operations which cannot be performed on pointers. Since, pointer stores address hence
we must ignore the operations which may lead to an illegal address, for example, addition, and
multiplication. A list of such operations is given below.
o ~Address = illegal
* POINTERS AND ARRAYS (POINTERS TO ARRAYS)
When an array is declared, the compiler allocates a base address and sufficient amount of storage to
contain all the elements of the array in continuous memory locations. The base address is the location of
the first element (index 0) of the array. The compiler also defines the array name as a constant pointer to
the first element. Suppose we declare an array x as follows:
Suppose the base address of x is1000 and assuming that each integer requires two bytes, the five elements
will be stored as follows:
The name x is defined as a constant pointer pointing to the first element, x [0] and therefore the value of x
is 1000, the location where x [0] is stored. That is,
If we declare p as an integer pointer, then we can make the pointer p to point to the array x by the
following assignment:
p=x;
Now we can access every value of x using p++ to move from one element to another.
Address of an element is calculated using its index and the scale factor of the data type.
For instance,
=1000 + (3 x 2)
When handling arrays, instead of using array indexing, we can use pointers to access array elements.
Note that *(p+3) gives the value of x [3].
#include<stdio.h>
void main()
int x[5]={1,2,3,4,5};
int *p=x;
int i;
for(i=0;i<5;i++)
In C, double pointers are those pointers which store the address of another pointer. The first pointer is
used to store the address of the variable, and the second pointer is used to store the address of the first
pointer. That is why they are also known as a pointer to pointer.
type **name;
Initialization:
#include<stdio.h>
intmain(){
// A variable
intvar=10;
// Pointer to int
int*ptr1=&var;
printf("var: %d\n",var);
printf("*ptr1: %d\n",*ptr1);
printf("**ptr2: %d",**ptr2);
return0;
}
Output:
var: 10
*ptr1: 10
**ptr2: 10
It can be defined as a procedure in which the size of a data structure (like Array) is changed during the
runtime.
C provides some functions to achieve these tasks. There are 4 library functions provided by C defined
under <stdlib.h> header file to facilitate dynamic memory allocation in C programming.
They are:
1. malloc()
2. calloc()
3. free()
4. realloc()
C malloc():
The “malloc” or “memory allocation” method in C is used to dynamically allocate a single large block of
memory with the specified size. It returns a pointer of type void which can be cast into a pointer of any
form. It doesn‟t initialize memory at execution time so that it has initialized each block with the default
garbage value initially.
Syntax of malloc() in C:
int *ptr;
For Example:
Example:
#include <stdio.h>
#include <stdlib.h>
int main()
int* ptr;
int n, i;
if (ptr == NULL) {
exit(0);
else {
ptr[i] = i + 1;
return 0;
Output:
C calloc() method:
“calloc” or “contiguous allocation” method in C is used to dynamically allocate the specified number of
blocks of memory of the specified type. It is very much similar to malloc() but has two different points
and these are:
Syntax of calloc() in C:
here, n is the no. of elements and element-size is the size of each element.
For Example:
Example of calloc() in C:
#include<stdio.h>
#include<stdlib.h>
intmain()
{
int*ptr;
intn,i;
n=5;
printf("Enter number of elements: %d\n",n);
ptr=(int*)calloc(n,sizeof(int));
if(ptr==NULL)
{
printf("Memory not allocated.\n");
exit(0);
}
else
{
printf("Memory successfully allocated using calloc.\n");
for(i=0;i<n;++i)
{
ptr[i]=i+1;
}
printf("The elements of the array are: ");
for(i=0;i<n;++i)
{
printf("%d, ",ptr[i]);
}
}
return0;
}
Output:
C free() method:
“free” method in C is used to dynamically de-allocate the memory. The memory allocated using functions
malloc() and calloc() is not de-allocated on their own. Hence the free() method is used, whenever the
dynamic memory allocation takes place. It helps to reduce wastage of memory by freeing it.
Syntax of free() in C:
free(ptr);
Example of free() in C:
#include <stdio.h>
#include <stdlib.h>
int main()
int n, i;
n = 5;
exit(0);
else
free(ptr);
free(ptr1);
return 0;
}
Output:
Enter number of elements: 5
C realloc() method:
Syntax of realloc() in C:
Example of realloc() in C:
#include <stdio.h>
#include <stdlib.h>
int main(){
int* ptr;
int n, i;
n = 5;
if (ptr == NULL)
exit(0);
else
ptr[i] = i + 1;
n = 10;
if (ptr == NULL)
printf("Reallocation Failed\n");
exit(0);
ptr[i] = i + 1;
free(ptr);
return 0;
}
Output:
C Preprocessor Directives:
It is a program that preprocesses the source code before it passes through the compiler.
In almost every C program we come across, we see a few lines at the top of the program preceded by a
hash (#) sign. They are called preprocessor directives and are preprocessed by the preprocessor before
actual compilation begins. Preprocessor directives are mostly used in defining macros, evaluating
conditional statements, source file inclusion, pragma directives, line control, error detection, etc.
The following table lists all the preprocessor directives available in the C programming language:
Preprocessor Directives Description
Syntax:
#define PI 3.14159
2. #include – File Inclusion Directive:
Syntax:
#include <file_name>
or
#include "filename"
#include <stdio.h>
Syntax:
#ifdef MACRO
controlled text
#endif
File management:
Why do we need File Handling in C?
So far the operations using the C program are done on a prompt/terminal which is not stored anywhere.
The output is deleted when the program is closed. But in the software industry, most programs are written
to store the information fetched from the program. The use of file handling is exactly what the situation
calls for.
In order to understand why file handling is important, let us look at a few features of using files:
Reusability: The data stored in the file can be accessed, updated, and deleted anywhere and
anytime providing high reusability.
Portability: Without losing any data, files can be transferred to another in the computer system.
The risk of flawed coding is minimized with this feature.
Efficient: A large amount of input may be required for some programs. File handling allows you
to easily access a part of a file using few instructions which saves a lot of time and reduces the
chance of errors.
Storage Capacity: Files allow you to store a large amount of data without having to worry about
storing everything simultaneously in a program.
Types of Files in C
A file can be classified into two types based on the way the file stores the data. They are as follows:
Text Files
Binary Files
1. Text Files
A text file contains data in the form of ASCII characters and is generally used to store a stream of
characters.
Each line in a text file ends with a new line character („\n‟).
2. Binary Files
A binary file contains data in binary form (i.e. 0’s and 1’s) instead of ASCII characters. They contain
data that is stored in a similar manner to how it is stored in the main memory.
The binary files can be created only from within a program and their contents can only be read by
a program.
C File Operations
C file operations refer to the different possible operations that we can perform on a file in C such as:
1. Creating a new file – fopen() with attributes as “a” or “a+” or “w” or “w+”
A file pointer is a reference to a particular position in the opened file. It is used in file handling to perform
all file operations such as read, write, close, etc. We use the FILE macro to declare the file pointer
variable. The FILE macro is defined inside <stdio.h> header file.
FILE* pointer_name;
Open a File in C
For opening a file in C, the fopen() function is used with the filename or file path along with the required
access modes.
Syntax of fopen()
FILE* fopen(const char *file_name, const char *access_mode);
Or
fp = fopen(“filename”, “mode”);
eg;
fp = fopen(“myfile.txt”,”r”);
Parameters
file_name: name of the file when present in the same directory as the source file. Otherwise, full
path.
Return Value
File opening modes or access modes specify the allowed operations on the file to be opened. They are
passed as an argument to the fopen() function. Some of the commonly used file access modes are listed
below:
r Open for reading. If the file does not exist, fopen( ) returns NULL.
If the file exists, its contents are overwritten. If the file does not
Open for writing.
w exist, it will be created.
Data is added to the end of the file. If the file does not exist, it
Open for append.
a will be created.
w+ Open for both reading and If the file exists, its contents are overwritten. If the file does not
Mode Meaning of Mode Description
Note: if you want to perform operations on a binary file, then you have to append „b‟ at the last. For
example, instead of “w”, you have to use “wb”, instead of “a+” you have to use “a+b”.
Comparisons:
#include <stdio.h>
#include <stdlib.h>
int main()
FILE* fptr;
"now exit.");
exit(0);
return 0;
Output
The file is not opened because it does not exist in the source directory. But the fopen() function is also
capable of creating a file if it does not exist. It is shown below
Create a File in C
The fopen() function can not only open a file but also can create a file if it does not exist already. For that,
we have to use the modes that allow the creation of a file if not found such as w, w+, wb, wb+, a, a+, ab,
and ab+.
FILE *fptr;
fptr = fopen("filename.txt", "w");
#include <stdio.h>
#include <stdlib.h>
int main()
// file pointer
FILE* fptr;
if (fptr == NULL) {
printf("The file is not opened. The program will exit now");
exit(0);
else {
return 0;
Output
The file read operation in C can be performed using functions fscanf() or fgets(). Both the functions
performed the same operations as that of scanf and gets but with an additional parameter, the file pointer.
There are also other functions we can use to read from a file. Such functions are listed below:
Function Description
fscanf() Use formatted string and variable arguments list to take input from a file.
So, it depends on you if you want to read the file line by line or character by character.
Example:
FILE * fptr;
fptr = fopen(“fileName.txt”, “r”);
fscanf(fptr, "%s %s %s %d", str1, str2, str3, &year);
char c = fgetc(fptr);
The getc() and some other file reading functions return EOF (End Of File) when they reach the end of the
file while reading. EOF indicates the end of the file and its value is implementation-defined.
Note: One thing to note here is that after reading a particular part of the file, the file pointer will be
automatically moved to the end of the last read character.
Write to a File
The file write operations can be performed by the functions fprintf() and fputs() with similarities to read
operations. C programming also provides some other functions that can be used to write data to a file such
as:
Function Description
Similar to printf(), this function use formatted string and varible arguments list to print output
fprintf()
to the file.
fputs() Prints the whole line in the file and a newline at the end.
Example:
FILE *fptr ;
fptr = fopen(“fileName.txt”, “w”);
fprintf(fptr, "%s %s %s %d", "We", "are", "in", 2012);
fputc("a", fptr);
Closing a File
The fclose() function is used to close the file. After successful file operations, you must always close a
file to remove it from the memory.
Syntax of fclose()
fclose(file_pointer);
Example:
FILE *fptr ;
fptr= fopen(“fileName.txt”, “w”);
---------- Some file Operations -------
fclose(fptr);