PPS UNIT-V-output
PPS UNIT-V-output
PPS UNIT-V-output
POINTERS
Introduction:
A pointer is a constant or variable that contains an address that can be used to access data.
Pointers are built on the basis of pointer constants.
Pointer constant:
A pointer constant is an address value that specifically represents a memory location in the computers main
memory.
Like every other constant in computer world a character constant cannot be changed.
Every time a program runs all variables in the program will get different addresses, this is because in a
computer modern operating systems can put a program in memory wherever it feels convenient.
Pointer constants are drawn from the set of addresses of a computer. They exist during the run time of a
computer. We cannot change them but we can only use them.
Being existed in the computer a pointer constant can be retrieved and saved inside a variable.
The address operator (&) extracts the address of a variable. Syntax: &variable_name
To print the address of a variable the conversion code %p can be used.
MD AFZAL Mob: 8179700193
Asst. Professor [email protected]
//Printing the address of variables
#include<stdio.h>
int main(void)
{
char a, b;
system(“cls”); //clrscr();
printf(“%p %p”, &a, &b);
getch();
return 0;
}
Output:
142300
142301
Pointer Variables:
A pointer constant can be saved in a pointer variable, and later can be used to access the value.
The type of a pointer must be specific to the type of the variable to which it is going to point. That is an
integer type of variables address can be saved into an integer type of pointer.
To store the address of a variable we need a special type of variable that is Pointer variable.
A single variables address can be saved into multiple pointers, so that we’ll have more number of pointers
pointing to the same location, and it is possible in C.
If a Pointer variable not pointing to anywhere, that is if we want to make sure that a pointer is not pointing
to any address, C provides a special null pointer (NULL) in the standard Input/Output stdio.h header file
for this purpose.
The indirection operator (*) can be used to dereference the pointer’s address.
The indirection operator is a unary operator whose operand must be a pointer value. The result is, a pointed
variables value that can be used for inspection or manipulation.
To access the variable a through pointer p, simply code *p.
To add 1 to the variable a’s content any of the following ways can be used
a++ a=a+1 *p=*p+1 (*p)++
The indirection and address operators are the inverse of each other, and when combined in an expression
they cancel each other. *&x SAME x
To declare a pointer variable the asterisk symbol (*) can be used along with type specification.
The following figure shows the declaration and definition of different pointer variables and their
corresponding data variable declarations.
Declaration Vs Redirection:
The asterisk operator can be used in two different contexts: for declaration and for redirection.
When asterisk is used for declaration, it is associated with a type.
Example: int* ptr; will declare an integer pointer.
When asterisk is used for redirection, it is associated with a pointer variable to get the data value of the
variable whose address is stored in that pointer.
Example: sum = *aptr + *bptr;
Like every other object in C, pointers must be initialized, before they can be used in the program.
Like variables, without initialization pointers will also have an unknown garbage value in them.
When program starts all uninitialized pointers will hold some unknown addresses which are pointing to
some unknown values.
Pointers to Pointers
In C, it is possible to use pointers that points to other pointers. That is, we can have a pointer pointing to a
pointer to an integer.
The following figure demonstrates this two level indirection:
Each level of pointer indirection requires a separate indirection operator when it is dereferenced.
#include<stdio.h>
int main(void)
{
int a;
int* p;
int** q;
int*** r;
system(“cls”); //clrscr();
p = &a;
q = &p;
r = &q;
printf("Enter a value:");
scanf("%d",&a);
printf("a's value is:%d",a);
printf("\nEnter a value:");
scanf("%d",p);
printf("a's value: %d %d", a, *p);
printf("\nEnter a value:");
scanf("%d",*q);
printf("a's value: %d %d %d", a, *p, **q);
printf("\nEnter a value:");
scanf("%d",**r);
printf("a's value: %d %d %d %d", a, *p, **q, ***r);
getch();
return 0;
}
Output:
Enter a value:4
a's value is:4
Enter a value:5
a's value: 5 5
Enter a value:6
a's value: 6 6 6
Enter a value:7
a's value: 7 7 7 7
A pointer to void is a generic type that is not associated with a reference type, that is it is not the address of
a character, an integer, a floating point or any other type.
It is compatible for assignment purpose only with all other types.
The name of an array is a pointer constant to the first element in the array. As it is a pointer constant its
value cannot be changed, that is it cannot be used as an lvalue.
The name of an array and the first element address both will represent the same memory location in
computer memory.
When the array name is dereferenced it is like dereferencing the first element of the array; that is it gives
the value of the first element array[0].
Remember, when array name is dereferenced, it refers only to the first element, not the whole array.
Besides indexing, programmers use another powerful method of moving through an array: pointer
arithmetic.
Pointer arithmetic offers a set of arithmetic operators for manipulating the addresses in pointer.
This technique is used to move back and forth through an array from element to element.
Having an array a, then ‘a’ is a constant pointing to the first element and a+1 is a constant pointing to the
second element.
If a pointer ptr is pointing to the second element of the array, then p-1 is a pointer pointing to the previous
(first) element and p+1 is a pointer to the next (third) element.
Given an array a, a+2 is the address two elements away from a, and a+3 is the address three elements away
from a. So the generalized notation will be as follows:
Given pointer ptr, ptr±n is a pointer to the value n elements away from ptr.
Indirection operator can be applied on pointer arithmetic to access the value from the location where the
pointer is pointing after pointer arithmetic.
Self-Referential Structures:
Self-Referential structures holds one or more pointers which point to the same structure type of structure,
as their member.
In simple words, structures pointing to the same type of structures are self-referential structure.
A self-Referential structure is essentially a structure definition which includes at least one member that is a
pointer to the structure of its own type.
See the following declaration of a tagged structure:
struct NODE
{
int data;
struct NODE* link;
};
The above illustrated structure declaration describes one NODE that comprises of two logical segments.
One of them stores data and the other one is a pointer indicating where the next component can be found. .
Several such inter-connected nodes create a chain of structures known as linked list.
The above declaration of structure can be used to create a chain of nodes, where each node is going to hold
some data and a link to another node.
Several of such nodes can be created and connected to form a data-structure known as linked list.
The above NODE is having only one data element and a link to the one other NODE of the same type. As
the NODE is having only a single linking pointer between the NODEs, we can also call the data structure
as single linked list.
The following program demonstrate the concept of single linked list:
struct NODE {
int data;
struct NODE* link;
};
#include <stdio.h>
struct NODE {
int data;
struct NODE* link;
};
int main(void)
{
struct NODE node1, node2, node3; // Node1
system("cls"); //clrscr();
// Initialization node1
node1.link = NULL;
node1.data = 10;
// Initialization node2
node2.link = NULL;
node2.data = 20;
// Initialization node3
node3.link = NULL;
node3.data = 30;
Self-referential structures are very useful in applications that involve linked data structures, such as linked
lists.
Unlike a static data structure such as array where the number of elements that can be inserted in the array is
limited by the size of the array, a self-referential structure can dynamically be expanded or contracted.
Operations like insertion or deletion of nodes in a self- referential structure involve simple and straight
forward alteration of pointers.
Memory Usage:
Memory allocated to a program is divided into program memory and data memory.
Program memory consists of memory used for main and all called functions.
Data memory consists of permanent definitions of global and local data and constants, dynamic data
memory.
main() function must be in memory all the time. Each called function must be in memory only when it is
called and becomes active.
If a function called more than once, the copies of the local variables of this function will be maintained
inside stack memory.
In addition to the stack memory, a separate memory area known as heap is also available. Heap memory is
unused memory allocated to the program and available to be assigned during execution. It is the memory
pool from which the memory is allocated when requested by the memory allocation functions.
Static memory allocation requires that the declaration and definition of memory be fully specified in the
source program.
The number of bytes reserved cannot be changed during run time of the program.
So far we used this technique for reserving memory for variables, arrays and pointers.
Dynamic memory allocation uses predefined functions to allocate and release memory for data while the
program is running.
Unlike static memory allocations, dynamic memory allocations have no identifier associated with it. It can
be accessed only through an address. That is to access data in dynamic memory we need a pointer.
The malloc() function allocates a block of memory that contains the number of bytes specified in its
parameter.
void main(void)
{
int* ptr;
int n, i, sum = 0;
void main(void)
{
int* ptr;
int n, i, sum = 0;
The realloc() function is advised to be used with much care. As a minor issue in the usage will lead to the
crash of the program.
Given a pointer to a previously allocated block of memory, realloc changes the size of the block by
deleting or extending the memory at the end of the block.
If the memory cannot be extended because of other allocations, realloc allocates a completely new block,
copies the existing memory locations to the new allocations, and deletes the old locations.
Syntax: void* realloc(void* ptr, int newSize);
void main(void)
{
int* ptr;
int n, i, sum = 0;
free(ptr);
}
Output:
Enter the number of elements you need from heap:2
Memory successfully allocated using calloc.
Enter 2 elements into the heap:4
2
The elements in heap are: 4, 2,
Enter the new size of heap:4
Memory successfully allocated using realloc.
Enter 4 elements into the heap:2
3
4
5
The elements in heap are: 2, 3, 4, 5,
Releasing Memory (free())
When memory locations allocated by malloc, calloc or realloc are no longer needed, they should be freed
using the free() function.
It is an error to free memory with a null pointer, a pointer to other than the first element of an allocated
block, a pointer that is different type than the pointer that allocated the memory.
It is also an error to refer to memory after it has been released.
Syntax: void free(void* ptr);
A file is an external collection of related data treated as a single unit. The primary purpose of a file is to
keep a record of data.
As the contents of primary memory are not permanent, and they will be lost when the computer is shut
down, we need files to store the data permanently.
Sometimes the collection of data will become too large to be maintained in main memory; in this case files
can be used to store the data in secondary memory.
Files are stored permanently in auxiliary or secondary memory, the most common secondary storage
devices are hard disk, CD, DVD and tape.
When the computer reads, the data move from the external device to memory and when it writes the data
move from memory to the external device.
This data movement uses a special work area known as a buffer. A buffer is a temporary storage area that
holds data when it is in transfer to or from the memory. The buffer acts like a synchronizer between the
physical devices and memory.
When a file is processed for data input, the data is read from the file up to the end of file (EOF). End file is
the terminator of the file which indicates the completion of data processing in the file.
The EOF will be automatically read and supplied to the program and it is the responsibility of the
programmer to keep track of it.
When a program is terminated, the entire data is lost. Storing in a file will preserve your data even if the
program terminates.
If you have to enter a large number of data, it will take a lot of time to enter them all. If you have a file
containing all the data, you can easily access the contents of the file using few commands in C.
You can easily move your data from one computer to another without any changes.
Types of Files
There are two types of files:
1. Text files
2. Binary files
1. Text files
Text files are the normal .txt files that you can easily create using Notepad or any simple text editors.
Generally text files consists of sequence of characters divided into lines with each line terminated by a
newline (\n).
When you open those files, you'll see all the contents within the file as plain text. You can easily edit or
delete the contents.
They take minimum effort to maintain, are easily readable, and provide least security and takes bigger
storage space.
2. Binary files
In C, you can perform four major operations on the file, either text or binary:
When working with files, you need to declare a pointer of type file. This declaration is needed for
communication between the file and program.
Syntax: FILE *fptr;
Here FILE is a predefined structure definition in stdio.h library file.
Note the * asterisk after the file type (FILE). It indicates that fptr is a pointer variable that contains the
address of the stream of file.
Opening a file is performed using the library function in the "stdio.h" header file: fopen().
The syntax for opening a file in standard I/O is: fptr = fopen("file_to_open","mode")
For Example: fopen("E:\\cprogram\\newprogram.txt","w");
Let's suppose the file newprogram.txt doesn't exist in the location E:\cprogram. The first function creates a
new file named newprogram.txt and opens it for writing as per the mode 'w'.
The writing mode allows you to create and edit (overwrite) the contents of the file.
fgetc() & fputc functions: Reading and Writing characters to a text file
Character input/output functions read/write one character at a time from/to a text stream.
These functions are divided into two general groups:
1. Input/output functions used only with terminal devices.
2. Input/output functions used with both terminal devices and text files.
When the file is no longer needed it should be closed to free the system resources.
Closing a file is performed using library function fclose().
Syntax: fclose(fptr); //fptr is the file pointer associated with file to be closed.
void main(void)
{
int num;
FILE *fptr;
fptr = fopen("C:\\program.txt","w");
if(fptr == NULL)
{
printf("No such file exitst…!");
exit(1);
}
fprintf(fptr,"%d",num);
fclose(fptr);
}
Output:
This program takes a number from user and stores in the file program.txt.
After you compile and run this program, you can see a text file program.txt created in C drive of your
computer. When you open the file, you can see the integer you entered.
void main(void)
{
int num;
FILE *fptr;
fscanf(fptr,"%d", &num);
If you have many records inside a file and need to access a record at a specific position, you need to loop
through all the records before it to get the record.
This will waste a lot of memory and operation time. An easier way to get to the required data can be
achieved using fseek().
As the name suggests, fseek() seeks the cursor to the given record in the file.
Syntax: void fseek(FILE * stream, long int offset, int whence)
o The first parameter stream is the pointer to the file. The second parameter is the position of the
record to be found, and the third parameter specifies the location where the offset starts.
Whence Meaning
SEEK_CUR Starts the offset from the current location of the cursor in the file.
void main(void)
{
FILE *fp;
fp = fopen("test.txt", "r");
ftell() in C is used to find out the position of file pointer in the file with respect to starting of the file.
Syntax of ftell() is: long ftell(FILE *pointer).
Consider below C program.
When the fscanf statement is executed word “Someone” is stored in string and the pointer is moved beyond
“Someone”. Therefore ftell(fp) returns 7 as length of “someone” is 6.
#include<stdio.h>
void main(void)
{
/* Opening file in read mode */
FILE *fp = fopen("test.txt","r");
The rewind function sets the file position indicator (file marker) to the beginning of the file irrespective of
its current location.
General Syntax: void rewind(FILE *fp);
It is equivalent to: void fseek(stream, 0L, SEEK_SET);
#include <stdio.h>
int main () {
char str[] = "ISL Engineering College.";
FILE *fp;
int ch;
}
fclose(fp);
return(0);
}
Output: file.txt
This is ISL Engineering College. This is ISL Engineering College.
This is ISL Engineering College.