08 Pointers
08 Pointers
1
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Basics of pointers
2
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Basic Concept
In memory, every data item occupies one or more contiguous memory cells.
• A cell in memory is typically a byte. The number of memory cells required to store a data item
depends on its type (char, int, double, etc.).
3
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Accessing the Address of a Variable
The address of a variable can be determined using the ‘&’ operator.
•The operator ‘&’ immediately preceding a variable returns the address of the variable
•& is the “address-of” operator
Example: &xyz
The ‘&’ operator can be used only with a simple variable or an array element.
&distance
&x[0]
4
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example
Consider the statement
1380
int xyz = 50; (xyz) 50
•This statement instructs the compiler to allocate a location for the integer
variable xyz, and put the value 50 in that location.
•The value 50 can be accessed by using either the name (xyz) or by looking
at whatever is written in the address (&xyz which equals 1380 in this
example).
5
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Pointer Declaration
A pointer is just a C variable whose value is the address of another variable!
Pointer variables must be declared before we use them.
General form:
data_type *pointer_name;
Example:
int *ptr;
Three things are specified in the above declaration:
• The asterisk (*) tells that the variable ptr is a pointer variable.
• ptr will be used to point to a variable of type int.
Just after declaring a pointer, ptr does not actually point to anything yet (remember: a pointer is also a
variable; hence can contain garbage until it is assigned to some specific value). You can iniialize or set
a pointer to the NULL pointer which points nowhere: int *ptr = NULL;
Pointers are variables and are stored in the memory. They too have their own addresses (like &ptr).
6
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example (Contd.)
int xyz = 50; 1380
(xyz) 50
int *ptr; // Here ptr is a pointer to an integer
ptr = &xyz; ----
1380
(ptr)
Since memory addresses are simply numbers, they can be assigned to some variables which
can be stored in memory.
•Such variables that hold memory addresses are called pointers.
•Since a pointer is a variable, its value is also stored in some memory location.
Once ptr has been assigned a valid memory address, the * operator can be used to access the
value at that address. * is the “value-at” operator; can be used only with a pointer variable
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example: Making a pointer point to a variable
int a = 10, b = 5; 10 20
a: 1026 20
int *x, *y;
x = &a; y = &b; b: 1036 5 23
5 23
5
*x = 20;
*y = *x + 3; x: 2044 1026 x 1026 x 1026
y = x;
y: 2056 1036 y 1036 y 1026
8
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Things to Remember
Pointers have types, e.g. :
int *count;
float *speed;
Pointer variables should always point to a data item of the same type.
double x;
int *p;
p = &x; // You should not generally do this, compiler will complain
However, type casting can be used in some circumstances – we will see examples later.
p = (int *)&x;
9
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Pointers and arrays
10
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Pointers and Arrays
11
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example
Consider the declaration:
int x[5] = {1, 2, 3, 4, 5};
int *p;
•Suppose that the base address of x is 2500, and each integer requires 4 bytes.
12
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example (contd)
int x[5] = {1, 2, 3, 4, 5};
int *p;
•Suppose we assign p = &x[0];
•Now we can access successive values of x by using p++ or p-- to move from one element
to another.
For any array A, we have: A+i = &A[i] is the address of A[i], and *(A+i) = A[i].
13
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Printing pointers with %p
#include <stdio.h>
int main ()
{
int A[4] = {2, 3, 5, 7}, i, *p;
for (i=0; i<4; ++i)
printf("&A[%d] = %p, A[%d] = %d\n", i, A+i, i, *(A+i));
p = A;
printf("p = %p, &p = %p\n", p, &p); return 0;
}
Output
But then, what is &A? &A[0] = 0x7ffd66659050, A[0] = 2
&A[1] = 0x7ffd66659054, A[1] = 3
It is not an int pointer. &A[2] = 0x7ffd66659058, A[2] = 5
p = 0x7ffd66659050,
&A[3] &p = A[3]
= 0x7ffd6665905c, 0x7ffd66659048
= 7
14
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Pointer to an array vs pointer to a pointer
#include <stdio.h>
int main ()
{
int A[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2}, *p;
printf("A = %p\n", A);
printf("A + 1 = %p\n", A + 1);
printf("&A = %p\n", &A);
printf("&A + 1 = %p\n\n", &A + 1);
Output
p = A;
A = 0x7ffd428a9520
printf("p = %p\n", p); A + 1 = 0x7ffd428a9524
printf("p + 1 = %p\n", p + 1); &A = 0x7ffd428a9520
printf("&p = %p\n", &p); &A + 1 = 0x7ffd428a9560
printf("&p + 1 = %p\n", &p +
p = 0x7ffd428a9520
1); return 0;
p + 1 = 0x7ffd428a9524
} &p = 0x7ffd428a9518
&p + 1 = 0x7ffd428a9520
15
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Pointer expressions
Pointer arithmetic
16
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Pointers in Expressions
Like other variables, pointer variables can be used in expressions.
If p is an int pointer, then *p is an int variable (like any other int variable).
17
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
You can do arithmetic on pointers themselves
What are allowed in C?
•Add an integer to a pointer.
•Subtract an integer from a pointer.
•Subtract one pointer from another.
• If p1 and p2 are both pointers to the same array, then p2–p1 gives the number of
elements between p1 and p2.
18
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Pointer arithmetic
19
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Scale Factor
We have seen that an integer value can be added to or subtracted from a pointer variable.
p = &x[1];
printf (“%d”, *p); // This will print 20
p++; // This increases p by the number of bytes for int
printf (“%d”, *p); // This will print 30
p = p + 2; // This increases p by twice the sizeof(int)
printf (“%d”, *p); // This will print 50
20
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
More on Scale Factor
char carr[5] = {‘A’, ‘B’, ‘p’, ‘?’, ‘S’};
int darr[5] = {10, 20, 30, 40, 50}
char *p; int *q;
When a pointer variable is increased by 1, the increment is not necessarily by one byte, but by the size of the data
type to which the pointer points.
This is why pointers have types (like int pointers, char pointers). They are not just a single “address” data type.
21
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Pointer types and scale factor
Data Type Scale Factor
char 1
int 4
float 4
double 8
22
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Scale factor may be machine dependent
• The exact scale factor may vary from one machine to another.
• Can be found out using the sizeof operator.
• You can supply a variable name or a variable type to it to get its size.
#include <stdio.h>
main( )
{
printf (“No. of bytes occupied by int is %d \n”, sizeof(int));
printf (“No. of bytes occupied by float is %d \n”, sizeof(float));
printf (“No. of bytes occupied by double is %d \n”,
sizeof(double)); printf (“No. of bytes occupied by char is %d \n”,
sizeof(char));
}
Output
23
Number of bytes occupied by
int is 4 Number of bytes
occupied by float is 4 Number
of bytes occupied by double is
8 Number of bytes occupied
by char is 1
Example of scale factors
#include <stdio.h>
int main ()
{
char C[10], *cp;
int I[20], *ip;
float F[30], *fp;
double D[40], *dp;
cp = C; printf("cp = %p, cp + 1 = %p\n", cp, cp+1);
ip = I; printf("ip = %p, ip + 1 = %p\n", ip, ip+1);
fp = F; printf("fp = %p, fp + 1 = %p\n", fp, fp+1);
dp = D; printf("dp = %p, dp + 1 = %p\n", dp, dp+1);
return 0;
} Output
cp = 0x7ffd297f1d8e, cp + 1 =
0x7ffd297f1d8f ip = 0x7ffd297f1b70, ip + 1
= 0x7ffd297f1b74 fp = 0x7ffd297f1bc0, fp +
1 = 0x7ffd297f1bc4 dp = 0x7ffd297f1c40, dp
+ 1 = 0x7ffd297f1c48
24
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Pointers and functions
25
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Passing pointers to a function
In C, arguments are passed to a function by value.
• The data items are copied to the function.
• Changes made in the called function are not reflected in the calling function.
26
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Passing pointers as arguments to functions
#include <stdio.h> #include <stdio.h>
int main() int main()
{ {
int a, b; int a, b;
a = 5; b = 20; a = 5; b = 20;
swap (a, b); swap (&a, &b);
printf (“a = %d, b = %d\n”, a, b); printf (“a = %d, b = %d\n”, a, b);
} }
void swap (int x, int y) void swap (int *x, int *y)
{ {
int t; int t;
t = x; x = y; y = t; t = *x; *x = *y; *y = t;
} }
Output Output
a = 5, b = 20 a = 20, b = 5
27
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
A useful application of pointers
In C, a function can only return a single value.
Suppose you want to write a function that computes two values. How to send both the
computed values back to the calling function (e.g., main function)?
One way:
- Declare variables within the main (calling) function.
- Pass addresses of these variables as arguments to the function.
- The called function can directly store the computed values in the variables declared
within main.
28
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example of “returning” multiple values using pointers
#include <stdio.h>
int f ( int a, int b, int *p, int *q )
{
*p = a + b;
*q = a - b;
return a * b;
}
int main () Output
{
int u = 55, v = 34, x, y, z; x = 89, y = 21, z = 1870
z = f (u, v, &x, &y);
printf(“x = %d, y = %d, z = %d\n”, x, y, z);
}
29
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Pointers or arrays in function prototypes?
There is no difference among the following functions prototypes.
In all the cases, A is an int pointer. It does not matter whether the actual parameter is the name of an int array or of
an int pointer. Inside the function, A is a copy of the address passed.
30
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
A function can return a pointer
A program to locate the first upper-case letter (if any) in a string
#include <stdio.h>
char *firstupper ( char S[] ) // You can use char *S as the formal parameter
{
while (*S) if ((*S >= ‘A’) && (*S <= ‘Z’)) return S; else ++S;
return NULL;
}
int main ()
{
char *p, S[100];
scanf(“%s”, S);
p = firstupper(S);
if (p) printf(“%c found\n”, *p); else printf(“No upper-case letter found\n”);
return 0;
}
Note: A function should not return a pointer to a local variable. After the function returns, the local variable no longer exists.
31
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Another application of Pointers:
Dynamic memory allocation
32
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Problem with arrays
Sometimes:
•Amount of data cannot be predicted beforehand (may be driven by user input).
•Number of data items keeps changing during program execution.
Example: Search for an element in an array of N elements
33
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Better solution
Dynamic memory allocation
•Know how much memory is needed after the program is run
• Example: ask the user to enter from keyboard
•Dynamically allocate only the amount of memory needed
34
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Dynamic Memory Allocation
35
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Memory Allocation Functions
malloc
•Allocates requested number of bytes and returns a pointer to the first byte of the
allocated space.
calloc
•Allocates space for an array of elements, initializes them to zero and then returns a
pointer to the first byte of the memory.
free
•Frees previously allocated space.
realloc
•Modifies the size of previously allocated space.
36
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Allocating a Block of Memory
General format:
ptr = (type *) malloc (byte_size);
37
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Allocating a Block of Memory
Examples
p = (int *) malloc(100 * sizeof(int));
•A memory space equivalent to (100 times the size of an int) bytes is reserved.
•The address of the first byte of the allocated memory is assigned to the pointer p of
type int *.
38
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Allocating a Block of Memory
39
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Points to Note
malloc always allocates a block of contiguous bytes.
•The allocation can fail if sufficient contiguous memory space is not available.
•If it fails, malloc returns NULL.
You can use exit(status) instead of return status. For using exit(), you
need to #include <stdlib.h>.
40
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example of dynamic memory allocation
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int *A, n, i;
printf(“How many integers will you enter? ”); scanf(“%d”, &n);
if (n <= 0) { printf(“Wow! How come?\n”); exit(1); }
A = (int *)malloc(n * sizeof(int));
if (A == NULL) { printf(“Oops! I cannot store so many integers.\n”); exit(2); }
for (i=0; i<n; ++i) {
printf(“Enter integer no. %d: “, i); scanf(“%d”, A+i);
}
/* Now, do what you want to do with the integers read and stored in A[] */
...
exit(0);
}
41
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Can we allocate only arrays?
Single variable allocations are useful for building linked structures as we will see later.
42
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Using the malloc’d Array
Once the memory is allocated, it can be used with pointers, or with array notation.
Example:
int *p, n, i;
scanf(“%d”, &n);
p = (int *) malloc (n * sizeof(int));
for (i=0; i<n; ++i)
scanf(“%d”, &p[i]);
The n integers allocated can be accessed as *p, *(p+1), *(p+2), ..., *(p+n-1)
43
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Releasing the allocated space: free
An allocated block can be returned to the system for future use, by the free function.
General syntax:
free (ptr);
where ptr is a pointer to a memory block which has been previously created using malloc (or
calloc or realloc).
No size is to be mentioned for the allocated block. The system remembers it. The function frees
the entire block allocated by an earlier malloc() type of call.
ptr must be the starting address of an allocated block. A pointer to the interior of a block cannot
be passed to free().
Dynamically allocated memory stays until explicitly freed or the program terminates.
You cannot free an array A[] defined like this: int A[50];
44
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example of free
45
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Altering the Size of a Block
Sometimes we need to alter the size of some previously allocated memory block.
•More memory needed.
•Memory allocated is larger than necessary.
How?
•By using the realloc function.
46
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Altering the Size of a Block (contd.)
•The new memory block may or may not begin at the same place as the old one.
• If it does not find space, it will create it in an entirely different region and move the
contents of the old block into the new block.
•The function guarantees that the old data remains intact.
•If it is unable to allocate, it returns NULL and frees the original block.
47
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example of realloc
int main ()
{
int *A = (int *)malloc(10 * sizeof(int)), allocsize = 10, n = 0, x;
48
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR