C Module 5
C Module 5
As you can see in the above figure, pointer variable stores the address of number variable, i.e.,
fff4. The value of number variable is 50. But the address of pointer variable p is aaa3.
By the help of * (indirection operator), we can print the value of pointer variable p.
Initialization of Pointer variable
Pointer Initialization is the process of assigning address of a variable to a pointer
variable. It contains the address of a variable of the same data type. In C language address
operator & is used to determine the address of a variable. The & (immediately preceding a
variable name) returns the address of the variable associated with it.
int a = 10;
int *ptr; //pointer declaration
ptr = &a; //pointer initialization
Pointer variable always points to variables of the same datatype. For example:
float a;
int *ptr = &a; // ERROR, type mismatch
While declaring a pointer variable, if it is not assigned to anything then it contains
garbage value. Therefore, it is recommended to assign a NULL value to it.
A pointer that is assigned a NULL value is called a NULL pointer in C.
Dereferencing of Pointer/Accessing a variable through its pointer
Once a pointer has been assigned the address of a variable, to access the value of the
variable, the pointer is dereferenced, using the indirection operator or dereferencing operator
*.
#include<stdio.h>
int main(){
int number=50;
int *p;
p=&number;//stores the address of number variable
printf("Address of number variable is %x \n",p);
/* p contains the address of the number therefore printing p gives the address of number. */
printf("Value of p variable is %d \n",*p);
/*As we know that * is used to dereference a pointer therefore if we print *p, we will get the
value stored at the address contained by p. */
return 0;
}
Output
Address of number variable is fff4
Value of p variable is 50
Pointer Program to swap two numbers without using the 3rd variable.
#include<stdio.h>
int main(){
int a=10,b=20,*p1=&a,*p2=&b;
printf("Before swap: *p1=%d *p2=%d",*p1,*p2);
*p1=*p1+*p2;
*p2=*p1-*p2;
*p1=*p1-*p2;
printf("\nAfter swap: *p1=%d *p2=%d",*p1,*p2);
return 0;
}
Output
Before swap: *p1=10 *p2=20
After swap: *p1=20 *p2=10
Pointer Increment and Scale Factor
We can use increment operator to increment the address of the pointer variable so that
it points to next memory location. The value by which the address of the pointer variable will
increment is not fixed. It depends upon the data type of the pointer variable.
For Example:
int *ptr;
ptr++;
It will increment the address of pointer variable by 2. So if the address of pointer variable is
2000 then after increment it becomes 2002.
Thus the value by which address of the pointer variable increments is known as scale factor.
The scale factor is different for different data types as shown below:
Char 1 Byte
Int 2 Byte
Float 4 Byte etc.
Pointer Arithmetic & Expressions
Like other variables pointer variables can be used in expressions.
1) If p1 and p2 are properly declared and initialized pointers, then the following statements are
valid:
Y=*p1**p2;
sum=sum+*p1;
*p2=*p2+10;
*p1=*p1+*p2;
*p1=*p2-*p1;
2) if p1 and p2 are properly declared and initialized pointers then, ‘C’ allows adding integers to
a pointer variable.
EX:
int a=5, b=10;
int *p1,*p2;
p1=&a;
p2=&b;
Now,
P1=p1+1=1000+2=1002; (Assume the starting address as 1000)
P1=p1+2=1000+ (2*2) =1004;
P1=p1+4=1000+ (2*4) =1008;
Here addition means bytes that pointer data type hold are subtracted number of times
that is subtracted to the pointer variable.
3) If p1 & p2 are properly declared and initialized, pointers then
‘C’ allows to subtract integers from pointers. From the above example,
P1=p1-1=1000-2=998;
P1=p1-2=1000-4=996;
P1=p1-4=1000-8=992;
P2=p2-2=3000-4=2996;
P2=p2-6=3000-12=2988;
Here the subtraction means byte that pointer data type hold are subtracted number of
times that is subtracted to the pointer variable.
4) If p1 & p2 are properly declared and initialize pointers, and both points to the elements of
same type. “Subtraction of one pointer from another pointer is also possible".
NOTE: this operation is done when the both pointer variable points to the elements of the
same array.
EX:
P2- P1 (It gives the number of elements between p1 and p2)
5) Pointer can also be used with increment and decrement operators.
POINTER AND ARRAYS
When an array in C language is declared, compiler allocates sufficient memory to
contain all its elements. Its base address is also allocated by the compiler.
Declare an array arr,
int arr[5] = { 1, 2, 3, 4, 5 };
Suppose the base address of arr is 1000 and each integer requires two bytes, the five elements
will be stored as follows:
Variable arr will give the base address, which is a constant pointer pointing to arr[0]. Hence arr
contains the address of arr[0] i.e 1000.
arr has two purpose -
It is the name of the array
It acts as a pointer pointing towards the first element in the array.
arr is equal to &arr[0] by default
NOTE: You cannot decrement a pointer once incremented. p-- won't work.
Pointer to an Array
Use a pointer to an array, and then use that pointer to access the array elements. For example,
#include<stdio.h>
void main()
{
int a[3] = {1, 2, 3};
int *p = a;
for (int i = 0; i < 3; i++)
{
printf("%d", *p);
p++;
}
return 0;
}
Output
123
Note
*(a+i) //pointer with an array
is same as:
a[i]
Pointer to Multidimensional Array
Let's see how to make a pointer point to a multidimensional array. In a[i][j], a will give
the base address of this array, even a + 0 + 0 will also give the base address, that is the address
of a[0][0] element.
Syntax:
*(*(a + i) + j)
Pointer and Character strings
Pointer is used to create strings. Pointer variables of char type are treated as string.
char *str = "Hello";
The above code creates a string and stores its address in the pointer variable str. The pointer str
now points to the first character of the string "Hello".
The string created using char pointer can be assigned a value at runtime.
char *str;
str = "hello";
The content of the string can be printed using printf() and puts().
printf("%s", str);
puts(str);
str is a pointer to the string and also name of the string. Therefore we do not need to use
indirection operator *.
Array of Pointers
Pointers are very helpful in handling character arrays with rows of varying lengths.
char *name[3] = {
"Adam",
"chris",
"Deniel"
};
//without pointer
char name[3][20] = {
"Adam",
"chris",
"Deniel"
};
In the second approach memory wastage is more, hence it is preferred to use pointer in such
cases.
Pointers as Function Argument in C
Pointer as a function parameter is used to hold addresses of arguments passed during
function call. This is also known as call by reference. When a function is called by reference any
change made to the reference variable will effect the original variable.
Call by Value Vs Call by Reference
(Pass by Value Vs Pass b y Reference)
Call By Value: In this parameter passing method, values of actual parameters are copied to
function’s formal parameters and the two types of parameters are stored in different memory
locations. So any changes made inside functions are not reflected in actual parameters of the
caller.
Call by Reference: Both the actual and formal parameters refer to the same memory locations,
so any changes made inside the function are actually reflected in actual parameters of the caller.
Call By Value Call By Reference
return 0; return 0;
} }
// Swap functions that swaps // Function to swap two variables
// two values // by references
void swapx(int x, int y) void swapx(int* x, int* y)
{ {
int t; int t;
t = x; t = *x;
x = y; *x = *y;
y = t; *y = t;
Output: Output:
x=20 y=10 x=20 y=10
a=10 b=20 a=20 b=10
#include <stdio.h>
int* larger(int*, int*);
void main()
{
int a = 15;
int b = 92;
int *p;
p = larger(&a, &b);
printf("%d is larger",*p);
}
int* larger(int *x, int *y) //Function
{
if(*x > *y)
return x;
else
return y;
}
STRUCTURE POINTER
It is defined as the pointer which points to the address of the memory block that stores
a structure.
Example:
struct point
{
int value;
};
int main()
{
struct point s;
struct point *ptr = &s;
return 0;
}
In the above code s is an instance of struct point and ptr is the struct pointer because it is
storing the address of struct point.
Accessing structure members using Pointer
To access members of a structure using pointers, we use the -> operator.
Example: Access members using Pointer.
#include <stdio.h>
struct person
{
int age;
float weight;
};
int main()
{
struct person *personPtr, person1;
personPtr = &person1;
printf("Enter age: ");
scanf("%d", &personPtr->age);
printf("Enter weight: ");
scanf("%f", &personPtr->weight);
printf("Displaying:\n");
printf("Age: %d\n", personPtr->age);
printf("weight: %f", personPtr->weight);
return 0;
}
In this example, the address of person1 is stored in the personPtr pointer using personPtr =
&person1;.
Now, you can access the members of person1 using the personPtr pointer.
By the way,
personPtr->age is equivalent to (*personPtr).age
personPtr->weight is equivalent to (*personPtr).weight
POINTER TO POINTER (DOUBLE POINTER)
A pointer to a pointer is a form of multiple indirections, or a chain of pointers. Normally,
a pointer contains the address of a variable. When we define a pointer to a pointer, the first
pointer contains the address of the second pointer, which points to the location that contains
the actual value as shown below.
A variable that is a pointer to a pointer must be declared as such. This is done by placing
an additional asterisk in front of its name. For example, the following declaration declares a
pointer to a pointer of type int
int **var;
#include <stdio.h>
int main ()
{
int var;
int *ptr;
int **pptr;
var = 3000;
/* take the address of var */
ptr = &var;
C malloc() function
The “malloc” or “memory allocation” function 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 it has
garbage value initially. If space is insufficient, allocation fails and returns a NULL pointer.
Syntax:
ptr = (cast-type*) malloc(byte-size)
Example:
ptr = (int*) malloc(100 * sizeof(int));
Since the size of int is 4 bytes, this statement will allocate 400 bytes of memory. And, the
pointer ptr holds the address of the first byte in the allocated memory.
#include <stdlib.h>
int main(){
int *ptr;
ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */
if (ptr != NULL) {
*(ptr + 5) = 480; /* assign 480 to sixth integer */
printf("Value of the 6th integer is %d",*(ptr + 5));
}
}
Output:
Value of the 6th integer is 480
calloc() function in C
The calloc() function allocates multiple block of requested memory.
It initially initializes all bytes to zero.
It returns NULL if memory is not sufficient.
Syntax of calloc()
ptr = (castType*)calloc(n, size);
Example:
ptr = (float*) calloc(25, sizeof(float));
The above statement allocates contiguous space in memory for 25 elements of type float.
#include <stdio.h>
int main() {
int i, * ptr, sum = 0;
ptr = calloc(10, sizeof(int));
if (ptr == NULL) {
printf("Error! memory not allocated.");
exit(0);
}
printf("Building and calculating the sequence sum of the first 10 terms \ n ");
for (i = 0; i < 10; ++i) { * (ptr + i) = i;
sum += * (ptr + i);
}
printf("Sum = %d", sum);
free(ptr);
return 0;
}
Result:
Building and calculating the sequence sum of the first 10 terms
Sum = 45
free() function
Dynamically allocated memory created with either calloc() or malloc() doesn't get freed on their
own. You must explicitly use free() to release the space.
Syntax of free()
free(ptr);
This statement frees the space allocated in the memory pointed by ptr.
Example:
#include <stdio.h>
int main() {
int* ptr = malloc(10 * sizeof(*ptr));
if (ptr != NULL)
{
*(ptr + 2) = 50;
printf("Value of the 2nd integer is %d",*(ptr + 2));
}
free(ptr);
}
Output
Value of the 2nd integer is 50
C realloc()
If the dynamically allocated memory is insufficient or more than required, you can
change the size of previously allocated memory using the realloc() function.
Syntax of realloc()
ptr = realloc(ptr, x);
Here, ptr is reallocated with a new size x.
Example
#include <stdio.h>
int main ()
{
char *ptr;
ptr = (char *) malloc(10);
strcpy(ptr, "Programming");
printf(" %s, Address = %u\n", ptr, ptr);
ptr = (char *) realloc(ptr, 20); //ptr is reallocated with new size
strcat(ptr, " In 'C'");
printf(" %s, Address = %u\n", ptr, ptr);
free(ptr);
return 0;
}
FILE MANAGEMENT IN C
A File can be used to store a large volume of persistent data. Different operations that can be
performed on a file are:
1. Creation of a new file (fopen with attributes as “a” or “a+” or “w” or “w++”)
2. Opening an existing file (fopen)
3. Reading from file (fscanf or fgets)
4. Writing to a file (fprintf or fputs)
5. Moving to a specific location in a file (fseek, rewind)
6. Closing a file (fclose)
File management functions
Create a File
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.
To create a file in a ‘C’ program following syntax is used,
FILE *fp;
fp = fopen ("file_name", "mode");
In the above syntax, the file is a data structure which is defined in the standard library.
fopen is a standard function which is used to open a file.
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.
fp is a file pointer which points to the type file.
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.
r - open a file in read mode
w - opens or create a text file in write mode
a - opens a file in append mode
r+ - opens a file in both read and write mode
a+ - opens a file in both read and write mode
w+ - opens a file in both read and write mode
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:
Closing a file
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.
Input/Output operation on File
getc() and putc() are the simplest functions which can be used to read and write
individual characters to a file.
#include<stdio.h>
int main()
{
FILE *fp;
char ch;
fp = fopen("one.txt", "w");
printf("Enter data...");
while( (ch = getchar()) != EOF) {
putc(ch, fp);
}
fclose(fp);
fp = fopen("one.txt", "r");
return 0;
}
fprintf() and fscanf()
The fprintf() function is used to write set of characters into file. It sends formatted output to a
stream. The fscanf() function is used to read set of characters from file. It reads a word from the
file and returns EOF at the end of file.
#include<stdio.h>
struct emp
{
char name[10];
int age;
};
void main()
{
struct emp e;
FILE *p,*q;
p = fopen("one.txt", "a");
q = fopen("one.txt", "r");
printf("Enter Name and Age:");
scanf("%s %d", e.name, &e.age);
fprintf(p,"%s %d", e.name, e.age);
fclose(p);
do
{
fscanf(q,"%s %d", e.name, e.age);
printf("%s %d", e.name, e.age);
}
while(!feof(q));
}
putw(), getw() functions are file handling function in C programming language which is used to
write an integer value into a file (putw) and read integer value from a file (getw).
putw function is used to write an integer into a file. In a C program, we can write integer value
in a file as below.
putw() Syntax
putw(i, fp);
where
i – integer value
fp – file pointer
getw() Syntax
getw function reads an integer value from a file pointed by fp. In a C program, we can read
integer value from a file as below.
getw(fp);
#include <stdio.h>
int main ()
{
FILE *fp;
int i=1, j=2, k=3, num;
fp = fopen ("test.c","w");
putw(i,fp);
putw(j,fp);
putw(k,fp);
fclose(fp);
fp = fopen ("test.c","r");
while(getw(fp)!=EOF)
{
num= getw(fp);
printf(“Data in test.c file is %d \n”, num);
}
fclose(fp);
return 0;
}
Data in test.c file is
1
2
3
There is no need to read each record sequentially, if we want to access a particular record.C
supports these functions for random access file processing.
1. fseek()
2. ftell()
3. rewind()
fseek():
This function is used for seeking the pointer position in the file at the specified byte.
Syntax: fseek( file pointer, displacement, pointer position);
Where
file pointer ---- It is the pointer which points to the file.
displacement ---- It is positive or negative. This is the number of bytes which are skipped
backward (if negative) or forward( if positive) from the current position. This is attached with L
because this is a long integer.
Pointer position:
This sets the pointer position in the file.
Example
1)fseek( p,10L,0)
0 means pointer position is on beginning of the file, from this statement pointer position is
skipped 10 bytes from the beginning of the file.
2)fseek( p,5L,1)
1 means current position of the pointer position. From this statement pointer position is
skipped 5 bytes forward from the current position.
3)fseek(p,-5L,1)
From this statement pointer position is skipped 5 bytes backward from the current position.
ftell()
This function returns the value of the current pointer position in the file.The value is count from
the beginning of the file.
Syntax: ftell(fptr);
Where fptr is a file pointer.
rewind()
This function is used to move the file pointer to the beginning of the given file.
Syntax: rewind( fptr);
Where fptr is a file pointer.
It is quite common that errors may occur while reading data from a file in C or writing data to a
file. For example, an error may arise due to the following:
When trying to read a file beyond indicator.
When trying to read a file that does not exist.
When trying to use a file that has not been opened.
When trying to use a file in an appropriate mode i.e., writing data to a file that has been
opened for reading.
When writing to a file that is write-protected i.e., trying to write to a read-only file.
Failure to check for errors results the program may behave abnormally. Therefore an
unchecked error may result in premature termination for the program or incorrect output. The
feof and ferror functions can help us to detect I/O errors in the files.
feof()-Test for end of a file
feof() function is a file handling function in C programming language which is used to find the
end of a file.
Declaration: int feof(FILE *fp)
feof functions is used to find the end of a file. In a C program, we use feof() function as below.
feof(fp);
where,
fp – file pointer
Example
/* Open, Read and close a file: Reading char by char */
# include <stdio.h>
int main( )
{
FILE *fp ;
char c ;
printf( "Opening the file test.c in read mode" ) ;
fp = fopen ( "test.c", "r" ) ; // opening an existing file
if ( fp == NULL )
{
printf ( "Could not open file test.c" ) ;
return 1;
}
printf( "Reading the file test.c" ) ;
while ( 1 )
{
c = fgetc ( fp ) ; // reading the file
if( feof(fp) )
break ;
printf ( "%c", c ) ;
}
printf("Closing the file test.c as end of file is reached.");
fclose ( fp ) ; // Closing the file
return 0;
}
The ferror() function tests for an error in reading from or writing to the given stream.
Following is the declaration for ferror() function.
int ferror(FILE *stream)
Parameters
stream − This is the pointer to a FILE object that identifies the stream.
Return Value
If the error indicator associated with the stream was set, the function returns a non-zero value
else, it returns a zero value.
Example
The following example shows the usage of ferror() function.
#include <stdio.h>
int main () {
FILE *fp;
char c;
fp = fopen("file.txt", "w");
c = fgetc(fp);
if( ferror(fp) ) {
printf("Error in reading from file : file.txt\n");
}
clearerr(fp);
if( ferror(fp) ) {
printf("Error in reading from file : file.txt\n");
}
fclose(fp);
return(0);
}
Assuming we have a text file file.txt, which is an empty file. Let us compile and run the above
program that will produce the following result because we try to read a file which we opened
in write only mode.
The arguments passed from command line are called command line arguments. These
arguments are handled by main() function.
To support command line argument, you need to change the structure of main() function as
given below.
1. int main(int argc, char *argv[] )
Here, argc counts the number of arguments. It counts the file name as the first argument.
The argv[] contains the total number of arguments. The first argument is the file name always.
Example
Let's see the example of command line arguments where we are passing one argument with file
name.
#include <stdio.h>
void main(int argc, char *argv[] ) {
printf("Program name is: %s\n", argv[0]);
program.exe hello
Output:
Program name is: program
First argument is: hello