Professional Documents
Culture Documents
5.1 Pointers: C Programming For Problem Solving (18CPS23)
5.1 Pointers: C Programming For Problem Solving (18CPS23)
5.1 Pointers
Memory Organization
Memory is organized as a sequence of byte sized locations (1 byte = 8bits). Each byte
in memory is associated with a unique address. Addresses are positive integer values that
range from zero to some positive integer constant corresponding to last location in the
memory.
Every object (data or program code) that is loaded into memory is associated with a
valid range of addresses, i.e. each variable and each function in a program starts at a
particular location, and spans across consecutive addresses from that point onwards
depending on the size of the data item.
Consider the statement int a = 10; This tells the compiler to
1. Reserve space in memory to hold a integer value.
2. Associate the name ‘a’ with this memory location.
3. Store the value 10 at this location.
This is as shown in the following memory map.
a Location Name
10 Value at Location
This operator when used as a prefix to a variable name gives the address of that
variable.
EX: Program to print the address of a variable along with its value.
#include<stdio.h>
void main( )
{
int a;
a = 10;
printf(“The address of a is %u\n”, &a);
printf(“The value of a is %d\n”, a);
}
Here %u is used for printing address values, because memory addresses are unsigned
integers.
Consider the declaration,
char a;
int b;
Assuming char requires 1 byte and int requires 4 bytes, memory space may be
reserved in the following way.
. .
. .
. .
For ‘a’ 2000
2001
2001
For ‘b’
2003
2004
. .
. .
. .
&a = 2000
&b = 2001
i.e. a variables address is the first byte occupied by the variable.
1004 2000
Lecture Notes C Programming for Problem Solving [18CPS23]
Note that ‘b’ is not a ordinary variable. It is a variable which contains the address of
another variable ‘a’. Such type of variable is called a pointer variable.
Pointer Declaration
The syntax for declaring a pointer variable is
datatype * Name_of_the_Pointer_Variable;
Here datatype can be
Primitive datatypes such as int, float char, etc
User defined datatypes
Name_of_the_Pointer_Variable is any valid variable name.
Note: The datatype of a pointer variable must be same as the type of the variable that it points
to.
int *P means P is a pointer to an integer i.e. it can hold the address of a integer
variable .
float *P means P is a pointer to a float i.e. it can hold the address of a floating point
variable.
char *P means P is a pointer to a character i.e. it can hold the address of a character
variable.
EX:
Valid in ‘C’ Invalid in ‘C’
int *P; int *P;
int a = 10; float a = 3.4;
P = &a; P = &a;
EX: The value stored at address 1000 can be obtained by *P [same as *(&a)]. Here P means
the address 1000 and *P means the contents at address 1000 which is 10.
EX: Program to illustrate the use of indirection operator ‘*’ to access the value pointed by a
pointer.
#include<stdio.h>
void main( )
{
int a, b;
int *P;
a = 10;
P = &a;
b = *P;
printf(“%d\n”, a);
printf(“%d\n”, b);
printf(“%d\n”, *P);
}
OUTPUT
10
10
10
a Location Name
? Unknown Value
The same thing applies to pointer variables also. Uninitialized pointers will have
unknown memory addresses or unknown values that will be interpreted as memory locations.
int *P;
P Location Name
Uninitialized pointers cause errors which are very difficult to debug. Hence it is
always good practice to assign a valid memory address or NULL value to a pointer.
EX:
Module 5 Prof. C K Marigowda & Prof. Arun K H 4
Dept. of ISE, AIT
Lecture Notes C Programming for Problem Solving [18CPS23]
int a;
int *P = &a;
int *Q = NULL;
Note: NULL is a pointer value which when assigned to a pointer variable indicates that the
pointer does not point to any part of the memory.
Example:
#include<stdio.h>
void main( )
{
int a, b, sum, diff;
printf(“Enter 2 numbers\n”);
scanf(“%d%d”, &a, &b);
− The statements here adds/ subtracts the values of a and b and the result is stored in the
memory location pointed to by *s and *d, which is same as the memory locations of
sum and diff respectively.
− Therefore, any change to the memory location by s and d in the function will be
reflected in the main function.
Note: The use of pointer variables for communicating between functions is called pass by
pointers or call by reference.
Example:
void main( )
{
int m, n;
m=10;
n=20;
callval(m,n);
printf("%d%d", m, n);
}
output
10 20
void main( )
{
int m, n;
m=10;
n=20;
callref(&m, &n);
printf("%d%d", m, n);
}
output
100 200
#include<stdio.h>
void main( )
{
int a, b, temp;
printf(“Enter 2 numbers\n”);
scanf(“%d%d”, &a, &b);
printf(“BEFORE SWAPPING\n”);
printf(“Value of a = %d \n”,a);
printf(“Value of b = %d \n”,b);
temp = a;
a = b;
b = temp;
printf(“AFTER SWAPPING\n”);
printf(“Value of a = %d \n”,a);
printf(“Value of b = %d \n”,b);
}
int a, b, temp;
printf(“Enter 2 numbers\n”);
scanf(“%d%d”, &a, &b);
printf(“BEFORE SWAPPING\n”);
printf(“Value of a = %d \n”,a);
printf(“Value of b = %d \n”,b);
swap(&a, &b);
printf(“AFTER SWAPPING\n”);
printf(“Value of a = %d \n”,a);
printf(“Value of b = %d \n”,b);
}
Note:
If ‘a’ and ‘b’ are passed by value, then the effect of swapping will not be seen in the
main function. The variables ‘a’ and ‘b’ will retain their values.
When only one value needs to be sent from the called function to the calling function,
we can use the ‘return’ statement.
When more than one value needs to be sent from the called function to the calling
function, we have to use call by reference.
void main( )
{
int a, b;
int *big;
printf(“Enter 2 numbers\n”);
scanf(“%d%d”, &a, &b);
4. Pointer to a Function
{
int res;
res = c + d;
return res;
}
void main( )
{
int a, b, res;
printf(“Enter 2 numbers\n”);
scanf(“%d%d”, &a, &b);
EX:
int a = 10; // integer variable
int *p; // pointer to an integer
int **q; // pointer to a pointer to an integer
p = &a;
q = &p;
q p a
3000 2000 10
The above shows a 2-level indirection, however, there is no limit as to how many levels of
indirection we can use.
Here,
p is the address of ‘a’ (2000)
*p is the contents or value at address 2000 i.e. 10
q is the address of p (3000)
*q is the contents or value at address 3000 (2000)
**q is the contents or value at address 2000 (10)
a = *p = **q
One way of obtaining the address of each element of an array is by using the ‘&’ operator.
For example, &a[0] gives the address of the first element, &a[1] gives the address of the
second element and so on.
However, the address of the first element (also called as the base address) is stored in the
name of the array i.e. a = &a[0]. Hence the name of the array ‘a’ can be considered as a
pointer, pointing to the first element of the array.
A second way of obtaining the address of each element of an array is by using the name of
the array which is basically a pointer. For example, ‘a’ gives the address of the first element,
‘a+1’ gives the address of the second element, ‘a+2’ gives the address of the third element
and so on. Meaning ‘a’ is same as &a[0], ‘a+1’ is same as &a[1] and so on.
Note: Adding an integer ‘n’ to a pointer, makes the pointer to point to a value ‘n’ elements
away i.e. if ‘a’ is a pointer and ‘n’ is a integer, a + n = a + n * (sizeof(one element)).
EX: In the above memory map ‘a’ = 1000,
a+3 = a + 3 * sizeof(one element);
Here a = 1000, assuming integer takes 4 bytes, sizeof(one element) = 4 and hence,
a+3 = 1000 + 3 * 4 = 1000 + 12 = 1012 = Address of a[3] i.e &a[3]
In general, the address of a[i] can be obtained as &a[i] or ‘a+i and the value of a[i] can be
obtained as a[i] or *(a+i).
Program to print the elements of an array along with their address using pointers
#include<stdio.h>
void main( )
{
int n, i, a[20] ;
printf(“Enter the number of elements\n”);
scanf(“%d”, &n);
printf(“Enter the elements\n”);
for( i = 0; i < n ; i + + )
{
scanf(“%d”, a+i ); // same as scanf(“%d”, &a[i] );
}
printf(“The entered elements value and their corresponding address are\n”);
for( i = 0; i < n ; i + + )
{
printf(“%p\t”, a+i ); //address
printf(“%d\n”, *(a+i) ); //value
}
}
5.6 Program to find the sum of all elements in an array using pointers
#include<stdio.h>
void main( )
{
int n, i, a[20], sum ;
int *p;
printf(“Enter the number of elements\n”);
scanf(“%d”, &n);
p = a; // p = &a[0];
printf(“Enter the elements\n”);
for( i = 0; i < n ; i + + )
{
scanf(“%d”, p+i );
}
sum = 0;
for( i = 0; i < n ; i + + )
{
sum = sum + *(p+i);
}
printf(“Sum of all elements = %d\n”, sum);
}
5.7 Develop a program using pointers to compute the sum, mean and standard deviation
of all elements stored in an array of 'n' real numbers. (Lab Program 14)
a[i] ( [ ]− )
mean = variance = = √
#include<stdio.h>
void main( )
{
int n, i;
float a[20], sum, mean, var, sd;
float *p;
p = a; // p = &a[0];
// To find variance
temp=0.0
for( i = 0; i < n ; i + + )
{
temp = temp + (*(p+i) - mean) * (*(p+i) - mean);
}
var = temp/n;
5.8 Preprocessors
Preprocessor Directives
− These are lines included in our program that start with the character '#'
− These lines of code do not end with semi colon.
Example
#define PI 3.14
#include<stdio.h>
Directive Description
#define Defines a macro substitution
#undef Undefines a macro
#include Specifies the files to be included
#ifdef Test for a macro definition
#endif Specifies the end of #if
#ifndef Test whether a macro is not defined
#if Test a compile time condition
#else Specifies alternatives when #if test fails
Example
#define PI 3.14
#define FALSE 0
#define TRUE 1
#define CAPITAL "Delhi"
Note:
1) A macro can include an expression as well.
Example:
#define D 44 - 22
#define A 78 + 32
In the program, if we have a statement like ratio = D / A then the result of preprocessor
substitution will be ratio = 44 -22 / 78 + 32
It is always a good practice to use parenthesis when using expressions with macros.
2) A macro can include literally anything that the programmer wants to have substitution
Example
#define TEST if(x>y)
#define AND
#define PRINTF printf("Very Good\n");
In the program, if we have a statement like TEST AND PRINT then the result of preprocessor
substitution will be if(x>y) printf("Very Good\n");
Example
In the program, if we have a statement like volume = CUBE(side); then the result of
preprocessor substitution will be volume = (side * side *side);
Note: Suppose if the statement is volume = CUBE( a+b ); then the result of preprocessor
substitution will be volume = ( a+b * a+b * a+b)
It is always a good practice to use parenthesis when using parameters with macros, i.e.
#include<stdio.h>
#define SQUARE(x) ((x) *(x))
void main( )
{
int m, n;
m =2;
n=3;
printf("%d\n", SQUARE(m));
printf("%d\n", SQUARE(n));
printf("%d\n", SQUARE(m+n));
}
Output
4
9
25
#include<stdio.h>
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
void main( )
{
int m, n
printf("Enter two numbers\n");
scanf("%d%d", &m, &n);
printf("Bigger of two numbers is %d\n", MAX(m, n));
}
Example
#include<stdio.h>
#define SQUARE(x) ((x) *(x))
#define CUBE(x) ((SQUARE(x)) *(x))
void main( )
{
int m=3;
printf("%d\n", CUBE(m));
}
Output
27
Example:
void main( )
{
................
#ifdef IBM_PC
{
// code for IBM_PC
}
#else
{
// code for HP machine
}
#endif
}
If we want to run the program on IBM_PC, then we include the directive #define IBM_PC in
the program, otherwise we don't.
Comparision between Macros and Function
Macros Functions
Macros are preprocessed Function is compiled
No type checking Type checking is done
Useful when small code appears many times Useful when large code appears many times
in the program in the program
5.11 Structures
Why structures?
If we want to store a number of data items of same datatype, we can use arrays. However, if
we want to store the information which is a collection of items of dissimilar datatype, we
cannot use arrays. This is where we use structures.
Structures Definition and Syntax
A structure is a collection of related information of possibly different datatype under one
name.
Syntax:
struct tagname
{
datatype member1;
datatype member2;
..
..
};
Where
– struct is the keyword.
– tagname is user defined name for structure.
– datatype can be any of the basic datatype (int, float, char etc) or user defined datatype.
– member1, member2 are attributes of the structure (also called members or fields).
Example:
struct student
{
char name[20];
int marks1;
int marks2;
int marks3;
char regno[10];
};
Just by defining a structure, memory will not be allocated for the various fields. It simply
describes a format called template to represent information as shown
name Array of 20 characters
marks1 Integer
marks2 Integer
marks3 Integer
regno Array of 10 characters
The “typedef” is a keyword that allows the programmer to create a new datatype name for an
existing datatype.
The general syntax for typedef is
typedef datatype userprovidedname;
Where
- typedef is the keyword.
- datatype is any existing datatype.
- userprovidedname is the name for the existing datatype. Usually this is written in
capital letters.
Advantages of typedef
It helps in self-documenting a program by allowing the use of more descriptive names
for the standard datatypes.
Complex and lengthy declarations can be reduced to short and meaningful
declarations.
Improves readability of the program.
Format 2:
struct student
{
char name[20];
int marks1;
int marks2;
int marks3;
char regno[10];
}a, b, c;
typedef struct
{
char name[20];
int marks1;
int marks2;
int marks3;
char regno[20];
}STD;
OR
struct student
{
char name[10];
int marks1;
int marks2;
int marks3;
char regno[10];
};
typedef struct student STD;
Here STD is a new datatype of type struct student. Therefore the statement
STD a, b;
creates 2 variables a, b of type STD.
Note:
1. The structure type declaration defines a template of the structure and does not tell the
compiler to reserve any space in memory. Memory is allocated only when the
structure is associated with a variable.
Example:
struct student
{
char name[20];
int marks1;
int marks2;
int marks3;
char regno[10];
};
struct student a, b, c;
Here each of the variable (a, b, c) will have 5 members ( name, marks1, marks2, marks3,
regno). The statement struct student a, b, c; sets aside space in memory. It makes
available space to hold all the members in the structure for all the structure variables
declared.
2. Usually structure type declaration appears at the top of the source code i.e. before any
variables or functions are defined. In such cases, the definition is global and can be
used by other functions.
Note – Before the dot operator there must always be a structure variable and after the dot
operator there must always be a structure member.
Structure Initialization
Like primary variables and arrays, structure variables can also be initialized where they are
declared. The format used is quite similar to that used to initialize arrays.
Array example:
int num[6] = {2, 4, 12, 5, 45, 5};
int num[ ] = {2, 4, 12, 5, 45, 5};
If the array is initialized where it is declared mentioning the dimension of the array is
optional.
Structure Example:
struct book
{
char name[10];
float price;
int pages;
};
struct book b1 = {“c++”, 150.00, 550};
struct book b2 = {“physics”, 150.80, 800};
OR
struct book
{
char name[10];
float price;
int pages;
} b1 = {“c++”, 150.00, 550}, b2 = {“physics”, 150.80, 800};
Note – C language does not permit the initialization of individual structure members within
the template. The initialization must be done only in the declaration of the actual variables.
Example:
struct person
{
int weight =60;
float height = 170.60;
}p1;
This is not permitted.
void main( )
{
struct student a, b;
clrscr( );
printf(“enter the name, m1, m2, m3 and regno of student1\n”);
scanf(“%s%d%d%d%s”,a.name, &a.marks1, &a.marks2, &a.marks3, a.regno);
printf(“enter the name, m1, m2, m3 and regno of student2\n”);
scanf(“%s%d%d%d%s”,b.name, &b.marks1, &b.marks2, &b.marks3, b.regno);
printf(“the information of student 1 is\n”);
printf(“%s%d%d%d%s”,a.name, a.marks1, a.marks2, a.marks3, a.regno);
printf(“the information of student 2 is\n”);
printf(“%s%d%d%d%s”,b.name, b.marks1, b.marks2, b.marks3, b.regno);
getch( );
}
Comments:
1. The declaration at the beginning of the program combines different datatypes into a
single entity called struct student. Here struct is a key word, student is the structure
name and the different datatype elements are structure members.
2. a, b are structure variables of the type struct student.
3. The structure members are accessed using dot operator. So to refer name we use
a.name, b.name and to refer marks1 we use a.marks1 and b.marks1. Before the dot we
have a structure variable and after the dot we have a structure member.
4. Since a.name is a string, its base address can be obtained by just mentioning a.name.
Hence the address operator (&) has been dropped while receiving the name in scanf.
5.15Array of structures
Suppose if we want to store data about a book, then the following structure may be used.
struct book
{
char name[10];
float price;
int pages;
};
Now, if we want to store data of 100 books we would be required to use 100 different
structure variables from b1 to b100 which is definitely not very convenient.
struct book
{
char name[10];
float price;
int pages;
};
main( )
{
struct book b[100];
int i;
clrscr( );
for(i=0; i<100; i++)
{
printf(“enter the name, price and number of pages of %d book\n”,i);
scanf(“%s %f %d ”,b[i].name, &b[i].price, &b[i].pages);
}
printf(“books information\n”);
printf(“name price number of pages\n”);
for(i=0; i<100; i++)
{
printf(“%s %f %d \n”, b[i].name, b[i].price, b[i].pages);
}
getch( );
}
Here the structure fields are still accessed using the dot operator and the array elements using
the usual subscript notation.
The values of a structure variable can be assigned to another structure variable of the same
type using the assignment operator ( = ). It is not necessary to copy the structure elements or
members piece-meal. Obviously programmers prefer assignment to piece-meal copying.
struct employee
{
char name[10];
int age;
float salary;
};
void main( )
{
struct employee e1 = {“Harish”, 30, 25000.00};
struct employee e2, e3;
//piece-meal copying
strcpy(e2.name, e1.name);
e2.age = e1.age;
e2.sal = e1.sal;
Output:
Harish 30 25000.00
Harish 30 25000.00
Harish 30 25000.00
Note:
1. Copying of all structure elements at one go is possible because the structure elements
are stored in contiguous memory locations.
2. Assignment or copying of different structure variables is invalid.
Example:
struct
{
char name[10];
int age;
float salary;
}a, b;
struct
{
char name[10];
int age;
float salary;
}c, d;
Example:
a==b //Invalid: Comparison is not allowed between structure variables.
a!=b //Invalid: Comparison is not allowed between structure variables.
However, the members of 2 structure variables of same type can be compared using relational
operators.
Example:
a.member1 = = b.member2 //Return true if they are same, false otherwise
a.member1 ! = b.member2 //Return true if they are not same, false otherwise
Note – The arithmetic, relational, logical and other various operations can be performed on
individual members of structures but not on structure variables.
Arrays Structures
1 An array is a collection of related data Structure is a collection of
elements of same datatype. variables of similar or dissimilar
datatype.
2 An array item can be accessed by using Structure items can be accessed
its subscript or by using dereferencing / using ‘.’or by using –> for
indirection (*) operator for pointers. pointers.
Example:
Write a C program with an appropriate structure definition and variable declaration to store
information about an employee using nested structures. Consider the following fields like
Ename, Empid, DOJ(Date, Month, Year) and Salary (Basic, DA, HRA).
#include<stdio.h>
struct doj
{
int date, month, year;
};
struct salary
{
float basic, da, hra;
};
struct employee
{
char ename[20];
int empid;
struct doj DOJ;
struct salary SALARY;
};
void main( )
{
struct employee e[100];
int n, i;
printf("enter the number of employees\n");
scanf("%d", &n);
printf("enter the details\n");
for(i=0; i<n; i++)
{
printf("enter the name\n");
scanf("%s", e[i].ename);
printf("enter the id\n");
scanf("%d", &e[i].empid);
printf("enter the date of birth (day/month/year)\n");
scanf("%d%d%d", &e[i].DOJ.date, &e[i].DOJ.month, &e[i].DOJ.year);
printf("enter the salary (basic/da/hra)\n");
scanf("%f%f%f", &e[i].SALARY.basic, &e[i].SALRY.da, &e[i].SALARY.hra);
}
printf("the employee details are \n");
printf("Name\t Empid\t Date\t Month\t Year\t Basic\t da\t hra\n");
for(i=0; i<n; i++)
{
printf("%s\t %d\t %d\t %d\t %d\t %f\t %f\t %f\n", e[i].ename, e[i].empid,
e[i].DOJ.date, e[i].DOJ.month, e[i].DOJ.year, e[i].SALARY.basic, e[i].SALARY.da,
e[i].SALARY.hra);
}
}
Here the members of the structure are passed as parameters to the function.
#include<stdio.h>
struct employee
{
char name[10];
int age;
float salary;
};
void main( )
{
struct employee e1 = {“Harish”, 30, 25000.00};
#include<stdio.h>
struct employee
{
char name[10];
int age;
float salary;
};
void main( )
{
struct employee e1 = {“Harish”, 30, 25000.00};
display(e1);
}
#include<stdio.h>
struct employee
{
char name[10];
int age;
float salary;
};
void main( )
{
struct employee e1 = {“Harish”, 30, 25000.00};
display(&e1);
}
5.19 Unions
Unions
A union is a collection of related information of possibly different datatype under one name.
It is a concept derived from structures. The main features that distinguish it form structures
are
1. The amount of memory allocated is equal to the size of the member that occupies largest
space.
2. The memory allocated is shared by individual members of union.
Syntax:
union tagname
{
datatype member1;
datatype member2;
..
..
};
Where
– union is the keyword.
– tagname is user defined name for union
– datatype can be any of the basic datatype (int, float, char etc) or user defined datatype.
– member1, member2 are attributes of the union (also called members or fields).
Example:
union item
{
int i;
double d;
char c;
};
1. The definition of a union does not allocate any memory since the definition is not
associated with any variable.
2. The different forms of variable declarations for structures, holds good for unions.
3. The union members are accessed exactly the same way in which the structure
elements are accessed i.e. using a ‘.’ operator.
4. The major difference between structures and unions is the way in which memory is
allocated.
Structure Union
1 The keyword ‘struct’ is used to start the The keyword ‘union’ is used to start the
declaration of a structure. declaration of a union.
2 The size of memory allocated by the The size of memory allocated by the
compiler is equal to or greater than the sum compiler is equal to the size of the member
of sizes of its members. that occupies largest space.
3 Memory allocated is unique (separate) for Memory allocated is shared (common) for
all members declared within the structure. all the members declared within the union.
4 Altering the value of a member will not Altering the value of any of the member will
affect other members of the structure. alter other member values.
5 Several members of a structure can be Only the first member of union can be
initialized at once. initialized.
6 Individual members can be accessed at a Only one member can be accessed at a time.
time.
#include<stdio.h>
struct student
{
char name[20];
int rollno;
int m1, m2, m3;
int avg;
};
void main( )
{
struct student s[100];
int n, i, sum=0, class_avg =0;