Pointers

Download as pdf or txt
Download as pdf or txt
You are on page 1of 62

Outline

• Derived Types

• Introduction to Pointers

• Pointer Declaration and Initialization

• Pointer Types

• Pointer pointing to one or more variables

• Pointer Usage and Arithmetic

• Pointers in 1D Array

1
Derived Types

2
Introduction to Pointers
• Contain memory addresses as their values
• Normal variables contain a specific value (direct reference)
Normal_variable

• Pointers contain address of a variable that has a specific value


(indirect reference)
• Indirection – referencing a pointer value
Pointer_variable Normal_variable

3
Pointer Declaration and Initialization
• * used with pointer variables
int *myPtr;

• Declares a pointer to an int (pointer of type int *)

• Multiple pointers require using a * before each variable


declaration
int *myPtr1, *myPtr2;

• Can declare pointers to any data type

• Initialize pointers to 0, NULL, or an address


• 0 or NULL – points to nothing (NULL preferred)
4
Pointer Type

5
6
Store address of variable to another
variable
int n;
int *q; // Declares pointer to int
q = &n; // address of n is stored in q

char a;
char *p; // Declares pointer to char
p = &a; // address of a is stored in p

float x;
float *r; // Declares pointer to float
r = &x; // address of x is stored in r
7
Define and Initialize Pointer variable

8
Pointer pointing to variable(s)

9
Demonstrate Pointer Usages
#include <stdio.h> Output:
int main (void)
15 13579
{
int a; 13579 15 15
int *p;
a = 15;
p= &a;
printf(“%d %u\n”, a , &a);
printf(“%u %d %d”, p, *p,
a);
return 0;
}

10
Program
#include <stdio.h> Output:
p = &a;
int main (void)
*q = 8; 6 8 20
{
int a, b, c; 6 8 20
int *p, *q, *r; *r = *p;
*r = a + *q + *&c;
a = 6;
b = 2; printf(“%d %d %d\n”, a, b, c);
printf(“%d %d %d”, *p, *q, *r);
p = &b; return 0;
q = p; }
r = &c;
11
Arrays
When an array is declared, compiler allocates sufficient amount of memory to contain
all the elements of the array.
Base address which gives location of the first element is also allocated by the
compiler. Suppose, we declare an array arr.
int arr[5] = {1, 2, 3, 4, 5};
Assuming that the base address of arr is 1000 and each integer requires 2 bytes.
Then 5 elements are stored as follows.

arr[0] arr[1] arr[2] arr[3] arr[4]

1000 1002 1004 1006 1008

Here, arr will give base address, which is a constant pointer pointing to the element
arr[0]. Therefore, arr contains the address of arr[0] i.e. 1000
arr is equal to &arr[0] //by default
12
Pointer
We can declare a pointer of type int to point to the array arr.
int *p;
p = arr;
or p = &arr[0]; //both statements are equivalent
Now, we can access every element of array arr using p++ to move from one
element to another.

Note: We cannot decrement a pointer once incremented p- - won’t work.

13
Pointer to Array
We can use a pointer to point to an Array. Then use that pointer to access that array.
int i;
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;
for (i=0; i<5; i++)
{
printf(“%d”, *p);
p++;
}
Note: pointer *p prints all the values that are stored in the array arr one by
one.

14
Replacing printf(“%d”, *p); statement in the previous program, with below
statements. Let’s observe the result.

printf(“%d”, arr[i]); prints array by incrementing index

printf(“%d”, i[arr]); prints array by incrementing index

printf(“%d”, arr + i); prints address of all the array elements

printf(“%d”, *(arr + i)); prints array by incrementing index

printf(“%d”, *arr); prints value of arr[0] only

arr++; compile time error, can’t change base address of array


15
16
Initializing a String
• A constant string can be initialized as:
char *s = “DTUIT”;

• Another possible way,


char *s;
strcpy(s, “DTUIT”);

17
String Using Pointer
#include <stdio.h> Note: Check for “Hello World” as
String
#include <stdlib.h>
int main()
{
char *s;
scanf("%s", s);
printf("The input is %s\n", s);
return 0;
}

18
Better Way
#include <stdio.h> Output:
Hello World
#include <stdlib.h>
int main()
{
char *s;
gets(s);
puts(s);
return 0;
}

19
Question
void Question()
{
char *string, *x;
strcpy(string, "Hello World.");
x = string;
for( ; *x != '\0'; x++)
{
printf("%c", *x);
}
printf("\n");
}

20
Pointer to an array
• We can also declare a pointer that can point to the whole
array instead of only one element of array.
• Useful in multidimensional array.
• Syntax: data_type (*var_name)[size_of_array];
Declaration: int (*ptr)[10]; // ptr is a pointer that
can point to an array of 10 integers.

p = 9584, ptr = 9584, arr= 9584


*p = 3, *ptr = 9584
p = 9588, ptr = 9604
*p = 5, *ptr = 9604

21
22
•p: is pointer to 0th element of the array arr, while ptr is a pointer that points to the
whole array arr.
•The base type of p is int while base type of ptr is ‘an array of 5 integers’.
•We know that the pointer arithmetic is performed relative to the base size, so if we
write ptr++, then the pointer ptr will be shifted forward by 20 bytes.
•On dereferencing a pointer expression we get a value pointed to by that pointer expression
• Pointer to an array points to an array, so on dereferencing it, we should get the array, and
the name of array denotes the base address.
•So whenever a pointer to an array is dereferenced, we get the base address of the array to
which it points.

23
Pointer Arithmetic and Array
float a[4];
Data Table
float *ptr;
Name Type Description Value
ptr = &(a[2]);
a[0] float float array element (variable) ?
*ptr = 3.14;
a[1] float float array element (variable) ?
ptr++;
a[2] float float array element (variable) ?
*ptr = 9.0;
ptr = ptr - 3;
a[3] float float array element (variable) ?

*ptr = 6.0; ptr float * float pointer variable


ptr += 2; *ptr float de-reference of float pointer ?
variable
*ptr = 7.0;

24
Pointer Arithmetic and Array
float a[4];
Data Table
float *ptr;
Name Type Description Value
ptr = &(a[2]);
a[0] float float array element (variable) ?
*ptr = 3.14;
a[1] float float array element (variable) ?
ptr++;
a[2] float float array element (variable) ?
*ptr = 9.0;
ptr = ptr - 3;
a[3] float float array element (variable) ?

*ptr = 6.0; ptr float * float pointer variable address of a[2]


ptr += 2; *ptr float de-reference of float pointer ?
variable
*ptr = 7.0;

25
Pointer Arithmetic and Array
float a[4];
Data Table
float *ptr;
Name Type Description Value
ptr = &(a[2]);
a[0] float float array element (variable) ?
*ptr = 3.14;
a[1] float float array element (variable) ?
ptr++;
a[2] float float array element (variable) 3.14
*ptr = 9.0;
ptr = ptr - 3;
a[3] float float array element (variable) ?

*ptr = 6.0; ptr float * float pointer variable address of a[2]


ptr += 2; *ptr float de-reference of float pointer 3.14
variable
*ptr = 7.0;

26
Pointer Arithmetic and Array
float a[4];
Data Table
float *ptr;
Name Type Description Value
ptr = &(a[2]);
a[0] float float array element (variable) ?
*ptr = 3.14;
a[1] float float array element (variable) ?
ptr++;
a[2] float float array element (variable) 3.14
*ptr = 9.0;
ptr = ptr - 3;
a[3] float float array element (variable) ?

*ptr = 6.0; ptr float * float pointer variable address of a[3]


ptr += 2; *ptr float de-reference of float pointer ?
variable
*ptr = 7.0;

27
Pointer Arithmetic and Array
float a[4];
Data Table
float *ptr;
Name Type Description Value
ptr = &(a[2]);
a[0] float float array element (variable) ?
*ptr = 3.14;
a[1] float float array element (variable) ?
ptr++;
a[2] float float array element (variable) 3.14
*ptr = 9.0;
ptr = ptr - 3;
a[3] float float array element (variable) 9.0

*ptr = 6.0; ptr float * float pointer variable address of a[3]


ptr += 2; *ptr float de-reference of float pointer 9.0
variable
*ptr = 7.0;

28
Pointer Arithmetic and Array
float a[4];
Data Table
float *ptr;
Name Type Description Value
ptr = &(a[2]);
a[0] float float array element (variable) ?
*ptr = 3.14;
a[1] float float array element (variable) ?
ptr++;
a[2] float float array element (variable) 3.14
*ptr = 9.0;
ptr = ptr - 3;
a[3] float float array element (variable) 9.0

*ptr = 6.0; ptr float * float pointer variable address of a[0]


ptr += 2; *ptr float de-reference of float pointer ?
variable
*ptr = 7.0;

29
Pointer Arithmetic and Array
float a[4];
Data Table
float *ptr;
Name Type Description Value
ptr = &(a[2]);
a[0] float float array element (variable) 6.0
*ptr = 3.14;
a[1] float float array element (variable) ?
ptr++;
a[2] float float array element (variable) 3.14
*ptr = 9.0;
ptr = ptr - 3;
a[3] float float array element (variable) 9.0

*ptr = 6.0; ptr float * float pointer variable address of a[0]


ptr += 2; *ptr float de-reference of float pointer 6.0
variable
*ptr = 7.0;

30
Pointer Arithmetic and Array
float a[4];
Data Table
float *ptr;
Name Type Description Value
ptr = &(a[2]);
a[0] float float array element (variable) 6.0
*ptr = 3.14;
a[1] float float array element (variable) ?
ptr++;
a[2] float float array element (variable) 3.14
*ptr = 9.0;
ptr = ptr - 3;
a[3] float float array element (variable) 9.0

*ptr = 6.0; ptr float * float pointer variable address of a[2]


ptr += 2; *ptr float de-reference of float pointer 3.14
variable
*ptr = 7.0;

31
Pointer Arithmetic and Array
float a[4];
Data Table
float *ptr;
Name Type Description Value
ptr = &(a[2]);
a[0] float float array element (variable) 6.0
*ptr = 3.14;
a[1] float float array element (variable) ?
ptr++;
a[2] float float array element (variable) 7.0
*ptr = 9.0;
ptr = ptr - 3;
a[3] float float array element (variable) 9.0

*ptr = 6.0; ptr float * float pointer variable address of a[2]


ptr += 2; *ptr float de-reference of float pointer 7.0
variable
*ptr = 7.0;

32
Passing 1-D array to a function
a single array element or an entire array can be passed to
a function. This can be done for both one-dimensional array or a
multi-dimensional array.
#include <stdio.h>
Using call by reference: void disp( int *num)
{
printf("%d ", *num);
}
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
for (int i=0; i<10; i++)
O/p 1 2 3 4 5 6 7 8 9 0 {
/* Passing addresses of array
elements*/
disp (&arr[i]);
}
return 0;
}

33
Entire array to a function as an argument
#include <stdio.h>
void myfuncn( int *var1, int var2)
{
for(int x=0; x<var2; x++)
{ printf("Value of var_arr[%d] is: %d \n", x, *var1);
/*increment pointer for next element fetch*/
var1++;
}
}
int main() {
int var_arr[] = {11, 22, 33, 44, 55, 66, 77};
myfuncn(var_arr, 7);
return 0;
}
34
Passing 2-D array in function Pointer to an array
of 3 integers(size
# include <stdio.h> of 1-D)
void show(int (*)[3],int,int);
int main() void show(int (*p)[3],int row,int col)
{ {
int a[3][3]={{1,2,3},{4,5,6},7,8,9}; int i,j;
show(a,3,3);
printf("\n\n\n");
for(i=0;i<row;i++)
return(0);
{
}
for(j=0;j<col;j++)
printf("\t %d",p[i][j]);
printf("\n");
}
Output: 1 2 3 }
4 5 6
7 8 9

35
36
Array of pointers
We can declare an array that contains pointers as its element. Every element of this
array is a pointer variable that can hold the address of any variable of appropriate
type.
Syntax: datatype *arrayname[size]; a b c
55 10
10 15
15
Example: int *arr[10];
2012 2560 3020
# include <stdio.h>
int main()
{
int *pa[3];
pa[0] pa[1] pa[2]
int i, a=5, b=10, c=15;
pa[0]= &a; 2012 2560 3020
pa[1]=&b; 5000 5008 5012
pa[2]=&c; pa[0] = 2293516 *pa[0] = 5
for(i=0;i<3;i++) pa[1] = 2293512 *pa[1] = 10
{ pa[2] = 2293508 *pa[2] = 15
printf("pa[%d] = %u\t",i,pa[i]);
printf("*pa[%d] = %d\n",i,*pa[i]);
}
37
}
Example2: Array of pointers can also contain address of
elements of another array
# include <stdio.h>
int main()
arr[0] arr[1] arr[2] arr[3]
{
int i, arr[4] = {5, 10, 15, 20}; 5 10 15 20
int *pa[4]; 1000 1002 1004 1006
for(i=0;i<4;i++)
pa[i] = &arr[i];
for(i=0;i<4;i++)
{ pa[0] pa[1] pa[2] pa[3]
printf("pa[%d] = %u\t",i,pa[i]); 1000 1002 1004 1006
printf("*pa[%d] = %d\n",i,*pa[i]); 5000 5008 5012 5018
}
} pa[0] = 8992 *pa[0] = 5
pa[1] = 8996 *pa[1] = 10
pa[2] = 9000 *pa[2] = 15
pa[3] = 9004 *pa[3] = 20
38
Void pointers
A pointer to void is a generic pointer that can point to any data type.
If we have a pointer to int, then it would be incorrect to assign the address of a
float variable to it but using void pointer we can store.
Void pointer is:
int i=2, *ip = &i;
float f=2.3, *fp=&f;
double d;
void *vp;
ip=fp;
vp=ip;
vp=fp;
vp=&d

39
Dynamic memory allocation
Dynamic memory allocation is the allocation of memory storage
for use in a computer program during the runtime of that
program.
Four Dynamic Memory Allocation Functions:
• Allocate memory - malloc(), calloc(), and realloc()
• Free memory - free()

40
malloc()
To allocate memory use
void *malloc(size_t size);

• Takes number of bytes to allocate as argument.


• Use sizeof to determine the size of a type.
• Returns pointer of type void *. A void pointer may
be assigned to any pointer.
• If no memory available, returns NULL.
e.g.
char *line;
int linelength = 100;
line = (char*)malloc(linelength);

41
malloc() example
To allocate space for 100 integers:
int *ip;
if ((ip = (int*)malloc(100 * sizeof(int))) == NULL){
printf("out of memory\n");
exit();
}
• Note we cast the return value to int*.
• On successfull malloc return a pointer to the newly allocated
memory.
• On error malloc return null;

42
Allocating memory for a struct

You can also allocate memory for a struct.


Example:
struct node *newPtr;
newPtr = (struct node *)malloc(sizeof(struct node));

• Memory allocated with malloc() lasts as long as you want it to.


• It does not automatically disappear when a function returns, as local
variables do
• To free the allocated memory there is a mechanism to free allocated
memory.
43
free()

To release allocated memory use


free()

• Deallocates memory allocated by malloc().


• Takes a pointer as an argument.
e.g.
free(newPtr);

• Freeing unused memory is a good idea, but it's not mandatory.


When your program exits, any memory which it has allocated but
not freed will be automatically released.
44
calloc()
• Similar to malloc(), the main difference is that the values stored in the
allocated memory space are zero by default. With malloc(), the allocated
memory could have any value.
• calloc() requires two arguments - the number of variables you'd like to
allocate memory for and the size of each variable. While in malloc() only
one arguments.
void *calloc(size_t nitem, size_t size);
Example: ptr =(int *)calloc(5,sizeof(int));
• This allocate a 5 blocks memory, each block contains 2 byte and starting
address is stored in a pointer variable ptr.
• Like malloc(), calloc() will return a void pointer if the memory allocation
was successful, else it'll return a NULL pointer.

45
realloc()
• When you want to increase or decrese memory allocated by malloc()
and calloc() use realloc().
• The function ralloc() is used to change the size of memory block.
• You give realloc() a pointer (such as you received from an initial call to
malloc()) and a new size, and realloc does what it can to give you a
block of memory big enough to hold the new size.
int *ip;
ip = (int*)malloc(100 * sizeof(int));
...
/* need twice as much space */
ip = (int*)realloc(ip, 200 * sizeof(int));

46
Write a C program to find sum of n elements entered by user. To perform this
program, allocate memory dynamically using malloc() function.

#include <stdio.h>
#include <stdlib.h>
int main()
{
int num, i, *ptr, sum = 0;
printf("Enter number of elements: ");
scanf("%d", &num);
ptr = (int*) malloc(num * sizeof(int)); //memory allocated using malloc
if(ptr == NULL)
{
printf("Error! memory not allocated."); exit(0);
}
printf("Enter elements of array: ");
Output:
for(i = 0; i < num; ++i)
{
Enter number of elements:5
scanf("%d", ptr + i); Enter elements of array: 2 5 7 8 9
sum += *(ptr + i); Sum = 31
}
printf("Sum = %d", sum);
free(ptr); return 0;
47
}
Write a C program to find sum of n elements entered by user. To perform this
program, allocate memory dynamically using malloc() function.

#include <stdio.h>
#include <stdlib.h>
int main()
{
int num, i, *ptr, sum = 0;
printf("Enter number of elements: ");
scanf("%d", &num);
ptr = (int*) malloc(num * sizeof(int)); //memory allocated
ptr = (int*) using malloc
calloc(num,sizeof(int));
if(ptr == NULL)
{
printf("Error! memory not allocated."); exit(0);
}
printf("Enter elements of array: ");
Output:
for(i = 0; i < num; ++i)
{
Enter number of elements:5
scanf("%d", ptr + i); Enter elements of array: 2 5 7 8 9
sum += *(ptr + i); Sum = 31
}
printf("Sum = %d", sum);
free(ptr); return 0;
48
}
Pointers and Structures
• Structure pointers are just like pointers to a variable of any data-type.

Declaring a structure pointer


struct <struct-name> *<pointer name>;

For eg.,

struct dob This declaration for a pointer to structure does not


{
allocate any memory for a structure but allocates
int day;
only for a pointer, so that to access structure’s
int month;
int year; members through pointer person1, we must

}; allocate the memory using malloc() function.


struct dob *person1; 49
Access Structure Members - Pointers

• Just like we use “.” operator to access members of a structure using a


normal variable, while for a structure pointer we use “ ->” notation.
• For eg.,

person1->date;
person1->month;
person1->year;

• Other method to access structure members through structure pointers.

(*person1).date; *person1.date;
(*person1).month; *person1.month;
(*person1).year; *person1.year;
50
Access Structure Members - Pointers

• When using structure pointers, we should take care of operator


precedence.
• Member operator “.” has higher precedence than “*”.
• person1 –> date and (*person1).date mean the same thing.
• *person.date will lead to error.

• The operator “–>” enjoys the highest priority among operators.


• ++person1 –> date will increment date, not person1.
• (++person1) –> date will do the intended thing.

• When pointer is incremented by one i.e., ++person1, it increases by


sizeof(dob), and points the next record, if any.

51
Example Program

The address of a structure type variable can be stored in a


structure type pointer variable
#include<stdio.h>

struct point
{
int x, y;
};

int main()
{
struct point p1 = {1, 2};

// p2 is a pointer to structure p1
struct point *p2 = &p1;

// Accessing structure members using structure pointer


printf("%d %d", p2->x, p2->y);
return 0;
} 52
Example Program using malloc()
#include<stdio.h>
struct point
{
int x, y;
};
int main()
{
struct point *p1;
p1=(struct point *)malloc(sizeof(struct point)); //dynamic memory allocation
printf("Enter x,y coordinates");
scanf("%d%d",&p2->x,&p2->y);
printf("%d %d", p2->x, p2->y); // Accessing structure members
return 0;
}

53
Subtracting two pointers of same type
#include<stdio.h>
void main ()
{
int i = 100;
int *p = &i;
int *q;
q = p;
p = p + 3;
printf("Pointer Subtraction: %d - %d = %d",p, q, p-q);
}

Output: (addresses may vary)


Pointer Subtraction: 1982076 - 1982064 = 3
54
Precedence of dereferencing operator and increment
decrement operator
The precedence level of * operator and increment/decrement operators
is same and their associativity is from right to left.
Suppose ptr is an integer pointer and x is an integer variable

ptr  25 38
x = *ptr++ = *ptr++ ==> *(ptr++) o/p x= 25

x = *++ptr = *++ptr ==> *(++ptr) o/p x=38

x= ++ *ptr = ++*ptr ==> ++(*ptr) o/p x = 26

x = (*ptr)++ o/p x= 25

55
Pointer to pointer
We can store the address of a pointer variable in some other variable, which
is known as a pointer to pointer variable.
The syntax of declaring a pointer to pointer is as-
data_type **pptr;
double asterisk used in the declaration of pointer to pointer.
int a= 5 ;
int *pa = &a;
int **ppa = &pa;
4000 3000 2000
3000 2000 5
ppa pa a
56
Output Questions Q2. #include<stdio.h>
#include <stdio.h>
int main()
Q1. {
#include "stdio.h" int i = 25;
int main() int *j;
{ int **k;
char a[] = { 'A', 'B', 'C', 'D' }; j = &i;
char* ppp = &a[0]; k = &j;
*ppp++; // Line 1 printf("%u %u %u ", k, *k, **k);
printf("%c %c ", *++ppp, --*ppp); return 0;
// Line 2 }
}

6684168 6684180 25
C A

57
#include<stdio.h>
int main()
{
char *ptr;
char string[] = "learn C from Welcome.com";
ptr = string;
ptr += 6;
printf("%s",ptr);
return 0;
}

C from Welcome.com

58
#include<stdio.h>
void function(char**);
int main()
{
char *arr[] = { "ant", "bat", "cat", "dog", "egg", "fly" };
function(arr);
return 0;
}
void function(char **ptr)
{
char *ptr1;
ptr1 = (ptr += sizeof(int))[-2];
printf("%s\n", ptr1);
}

cat

59
#include<stdio.h>
int main()
{
struct node
{
int a, b, c;
};
struct node num = {3, 5, 6};
struct node *ptr = & num;
printf("%d\n", *((int*)ptr + 1 + (3-2)));
return 0;
}

Output: 6

60
#include<stdio.h>
int main()
{
int *iptr;
int i, arr[2][2] = {10, 11, 12, 13};
iptr = *arr ;
printf("%d ", *(iptr+2));
return 0;
}

61
References

• https://cse.iitkgp.ac.in/~bivasm/pds_notes/
• https://www.geeksforgeeks.org/
• https://overiq.com/c-programming-101/
• https://www.oreilly.com/library/view/understanding-and-
using/9781449344535/ch04.html
• https://www.javatpoint.com/pointer-arithmetic-in-c
• https://www.cs.swarthmore.edu/~newhall/cs31/resources/C-structs_pointers.php
• http://www2.ece.ohio-state.edu/~degroat/EG167C/Lecture%2014%20-
%20Pointers%20-%2006.ppt

62

You might also like