UNIT- 5
Pointers in C
The pointer in C language is a variable which stores the address of another variable. This variable can be of type int, char, array, function, or any other pointer. The size of the pointer depends on the architecture. However, in 32-bit architecture the size of a pointer is 2 byte.
Consider the following example to define a pointer which stores the address of an integer.
- Int n = 10;
- Int* p = &n; // Variable p of type pointer is pointing to the address of the variable n of type integer.
Declaring a pointer
The pointer in c language can be declared using * (asterisk symbol). It is also known as indirection pointer used to dereference a pointer.
- Int *a;//pointer to int
- Char *c;//pointer to char
Pointer Example
An example of using pointers to print the address and value is given below.
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.
Let's see the pointer example as explained for the above figure.
- #include<stdio.h>
- Int main(){
- Int number=50;
- Int *p;
- p=&number;//stores the address of number variable
- Printf("Address of p 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
Address of p variable is fff4
Value of p variable is 50
Pointer to array
- Int arr[10];
- Int *p[10]=&arr; // Variable p of type pointer is pointing to the address of an integer array arr.
Pointer to a function
- Void show (int);
- Void(*p)(int) = &display; // Pointer p is pointing to the address of a function
Pointer to structure
- Struct st {
- Int i;
- Float f;
- }ref;
- Struct st *p = &ref;
Advantage of pointer
1) Pointer reduces the code and improves the performance, it is used to retrieving strings, trees, etc. and used with arrays, structures, and functions.
2) We can return multiple values from a function using the pointer.
3) It makes you able to access any memory location in the computer's memory.
Usage of pointer
There are many applications of pointers in c language.
1) Dynamic memory allocation
In c language, we can dynamically allocate memory using malloc() and calloc() functions where the pointer is used.
2) Arrays, Functions, and Structures
Pointers in c language are widely used in arrays, functions, and structures. It reduces the code and improves the performance.
Address Of (&) Operator
The address of operator '&' returns the address of a variable. But, we need to use %u to display the address of a variable.
- #include<stdio.h>
- Int main(){
- Int number=50;
- Printf("value of number is %d, address of number is %u",number,&number);
- Return 0;
- }
Output
Value of number is 50, address of number is fff4
NULL Pointer
A pointer that is not assigned any value but NULL is known as the NULL pointer. If you don't have any address to be specified in the pointer at the time of declaration, you can assign NULL value. It will provide a better approach.
Int *p=NULL;
In the most libraries, the value of the pointer is 0 (zero).
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
Reading complex pointers
There are several things which must be taken into the consideration while reading the complex pointers in C. Lets see the precedence and associativity of the operators which are used regarding pointers.
Operator | Precedence | Associativity |
(), [] | 1 | Left to right |
*, identifier | 2 | Right to left |
Data type | 3 | - |
Here,we must notice that,
- (): This operator is a bracket operator used to declare and define the function.
- []: This operator is an array subscript operator
- * : This operator is a pointer operator.
- Identifier: It is the name of the pointer. The priority will always be assigned to this.
- Data type: Data type is the type of the variable to which the pointer is intended to point. It also includes the modifier like signed int, long, etc).
How to read the pointer: int (*p)[10].
To read the pointer, we must see that () and [] have the equal precedence. Therefore, their associativity must be considered here. The associativity is left to right, so the priority goes to ().
Inside the bracket (), pointer operator * and pointer name (identifier) p have the same precedence. Therefore, their associativity must be considered here which is right to left, so the priority goes to p, and the second priority goes to *.
Assign the 3rd priority to [] since the data type has the last precedence. Therefore the pointer will look like following.
- Char -> 4
- * -> 2
- p -> 1
- [10] -> 3
The pointer will be read as p is a pointer to an array of integers of size 10.
Example
How to read the following pointer?
- Int (*p)(int (*)[2], int (*)void))
Explanation
This pointer will be read as p is a pointer to such function which accepts the first parameter as the pointer to a one-dimensional array of integers of size two and the second parameter as the pointer to a function which parameter is void and return type is the integer.
Variable
A variable is a name, set to a piece of memory in the RAM, which can be used to store and access the data. The value stored in the allocated (selected) memory may change as the program execution progresses so called variable.
A variable may take one or more bytes of memory according to the data type we use while declaring the variable.
Any variable of any type has three common characteristics, which are
- Name of the variable,
- Value of the variable and
- The Address of variable
Name is the label of a variable (memory allocation) with which value can be assigned, modified and accessed
1 2 3 | Price=45.75; /* assigning a value */ Price=price+10.50; /* modifying the value */ Printf("%f",price); /* accessing and printing the value */ |
Value is the data of any type stored in the memory in a binary format.
Address
As we discoursed earlier, the total memory is divided into number of bytes and each byte in the memory is identified with its serial number or byte number or we can call it as an address. It is always a positive number.
According to the type, a variable may take one or more bytes of memory but, the first byte number or higher byte number is considered as the address of variable.
How to get the address of a variable?
We can get the address of any variable using a unary operator called Address of operator &. Writing & operator as a prefix to the variable gives the address of variable. As the address of any variable is a positive number, the format specifier %u or %p or %x is used while printing the address. %u prints the address in decimal, %p and %x print the addresses in hexadecimal.
1 2 3 4 5 6 7 8 9 10 | #include <stdio.h> Int main() { Short x=10; Printf("Value %d",x); /* prints the value of x */ Printf("\nAddress of x %u",&x); /* prints the address of x in decimal */ Printf("\nAddress of x %x",&x); /* prints the address of x in hexadecimal */ Printf("\nAddress of x %p",&x); /* prints the address of x in hexadecimal */ Return 0; } |
Output in Turbo C:
Value 10
Address of x 65524
Address of x fff4
Address of x FFF4P
As the turbo C 3.0 is developed for 16bit system, address of any variable is a 16bit positive number (65524 – 1111 1111 1111 0100)
Output in Linux gcc:
Execution1:
x=10
Address of x 3217705836
Address of x bfca4b6c
Address of x oxbfca4b6c
Execution2:
x=10
Address of x 3220131100
Address of x 0xbfef4d1c
As the Ubuntu Linux 9.10 gcc is developed for 32bit systems, address of any variable is a 32bit number (3220131100 – 1011 1111 1110 1111 0100 1101 0001 1100).
Note: The address of a variable changes execution to execution that we can observe from the above two executions.
1 2 3 4 5 6 7 8 9 10 | #include<stdio.h> Int main() { Short x=45,y=52; Printf("x=%d",x); Printf("\ny=%d",y); Printf("\nAddress of x %u",&x); Printf("\nAddress of y %u",&y); Return 0; } |
Output:
x=45
y=52
Address of x 65494
Address of y 65492
Here x and y are a series of variables of short type, the memory allocation of which allocate in adjacent memory allocations.
We can’t get the address of a register variable
The storage specifier “register” allocates the variable in the CPU registers. We know that, it is not possible to get the address of a CPU register. Hence the compiler throws an error when we try to access the address of a register variable.
1 2 3 4 5 6 7 8 | #include<stdio.h> Int main() { Register short x=1; Printf("\nValue of x %d",x); Printf("\nAddress of x %u",&x); Return 0; } |
Output:
Error demo.c 6: Must take address of a memory location in function main
*** 1 errors in Compile ***
Summarizing address of operator &
- When a variable is declared then the memory of which is allocated in the free memory.
- Any variable of any type may take one or more bytes of memory but the higher byte number is considered as the address of memory allocation. It is always a positive number (unsigned). %u ,%x or %p are used to print the address.
- Address of (&) is a unary operator used to get the address of any specified variable.
- We can’t use the address of operator with the register variable.
Declaration of C Pointer variable
General syntax of pointer declaration is,
Datatype *pointer_name;
Data type of a pointer must be same as the data type of the variable to which the pointer variable is pointing. Void type pointer works with all data types, but is not often used.
Here are a few examples:
Int *ip // pointer to integer variable
Float *fp; // pointer to float variable
Double *dp; // pointer to double variable
Char *cp; // pointer to char variable
Initialization of C Pointer variable
Pointer Initialization is the process of assigning address of a variable to a pointer variable. Pointer variable can only contain 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.
#include<stdio.h>
Void main()
{
Int a = 10;
Int *ptr; //pointer declaration
Ptr = &a; //pointer initialization
}
Pointer variable always point to variables of same datatype. Let's have an example to showcase this:
#include<stdio.h>
Void main()
{
Float a;
Int *ptr;
Ptr = &a; // ERROR, type mismatch
}
If you are not sure about which variable's address to assign to a pointer variable while declaration, it is recommended to assign a NULL value to your pointer variable. A pointer which is assigned a NULL value is called a NULL pointer.
#include <stdio.h>
Int main()
{
Int *ptr = NULL;
Return 0;
}
Using the pointer or Dereferencing of Pointer
Once a pointer has been assigned the address of a variable, to access the value of the variable, pointer is dereferenced, using the indirection operator or dereferencing operator*.
#include <stdio.h>
Int main()
{
Int a, *p; // declaring the variable and pointer
a = 10;
p = &a; // initializing the pointer
Printf("%d", *p); //this will print the value of 'a'
Printf("%d", *&a); //this will also print the value of 'a'
Printf("%u", &a); //this will print the address of 'a'
Printf("%u", p); //this will also print the address of 'a'
Printf("%u", &p); //this will print the address of 'p'
Return 0;
}
Points to remember while using pointers
- While declaring/initializing the pointer variable, * indicates that the variable is a pointer.
- The address of any variable is given by preceding the variable name with Ampersand &.
- The pointer variable stores the address of a variable. The declaration int *a doesn't mean that a is going to contain an integer value. It means that a is going to contain the address of a variable storing integer value.
- To access the value of a certain address stored by a pointer variable, * is used. Here, the * can be read as 'value at'.
1) If p1 and p2 are properly declared and initialized pointers, then the following statements are valid:
Y=*p1**p2;
Sum=sum+*p1;
Z=5*-*p2/ *p1;
*p2=*p2+10;
*p1=*p1+*p2;
*p1=*p2-*p1;
NOTE: in the third statement there is a blank space between ‘/’ and * because the symbol /*is considered as beginning of the comment and therefore the statement fails.
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;
P1=p1+2=1000+ (2*2) =1004;
P1=p1+4=1000+ (2*4) =1008;
P2=p2+2=3000+ (2*2) =3004;
P2=p2+6=3000+ (2*6) =3012;
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.
Ex:
int a=10;
int *b;
b=&a;
EXAMPLE PROGRAM:
Write a function to calculate the roots. The function must use two pointer parameters, one to receive the coefficients a, b and c and the other to send roots to calling function.
01 | #include<stdio.h> | |
02 | #include<math.h> | |
03 | Roots (p, q) | |
04 | Float*p,*q; | |
05 | { | |
06 | *q= (–(*(p+1) +sqrt((*(p+1))*(*(p+1))–4*(*p)*(*(p+2))))/ | |
07 | (2*(*p)); | |
08 | *(q+1) = (–(*(p+1)-sqrt((*(p+1))*(*(p+1))–4*(*p)*(*(p+2))))/ | |
09 | (2*(*p)); | |
10 | } | |
11 | Voidmain () | |
12 | { | |
13 | FloatA [3], R [2]; | |
14 | Inti; | |
15 | Printf(‘‘Enter values fora, b, c’’); | |
16 | For(i=0; i< = 2; i++) | |
17 | Scanf(‘‘%f’’, A+i); | |
18 | Roots (A, R); | |
19 | Printf(‘‘root1 = %f’’, *(R+0)); | |
20 | Printf(‘‘root2=%f’’, *(R+1)); | |
21 | } | |
22 |
| |
Write a ‘C’ program to compute the sum of all elements stored in an array Using pointers.
01 | /*program to compute sum of all elements stored in an | |
02 | Array */ | |
03 | #include<stdio.h> |
04 | #include<conio.h> |
05 | Main () | |
06 | { | |
07 | Inta [10], I, sum=0,*p; | |
08 | Printf(“enter 10 elements \n”); | |
09 | For(i=0; i<10; i++) | |
10 | Scanf(“%d”, & a[i]); | |
11 | p = a; | |
12 | For(i = 0; i<10; i++) | |
13 | { | |
14 | Sum = sum*p; | |
15 | p++; | |
16 | } | |
17 | Printf(“the sum is % d”, sum); | |
18 | Getch (); | |
19 | } |
Write a ‘C’ program using pointers to determine the length of a character String.
01 | /*program to find the length of a char string */ | |
02 | #include<stdio.h> | |
03 | #include<conio.h> | |
04 | #include<string.h> | |
05 | Main () | |
06 | { | |
07 | Char str [20].*p; | |
08 | Int l=0; | |
09 | Printf(“enter a string \n”); | |
10 | Scanf(“ % s”, str); | |
11 | p=str; | |
12 | While(*p!=’\0’) | |
13 | { | |
14 | l++; | |
15 | p++; | |
16 | } | |
17 | Printf(“the length of the given string is %d”, l); | |
18 | Getch (); | |
19 | } |
We know it can express multiple variable by using arithmetic operator into a equation and we also did it before many time to calculate in program.
Example: If x, y and sum be float type variable then the statement of addition between x and y and assigning this result to another variable sum will be
Float x, y, sum;
Sum = x + y;
Similarly, we can do it with pointers but not with pointers variable. The following statement is valid.
Floatvar_one, var_two, *a, *b, sum;
Var_one = 10, var_two = 20;
a = &var_one, b = &var_two;
Sum = *a + *b;
Focus on fourth line. Similarly, we can express this for subtraction, multiplication, division. Remember for division, space from division operator is major important. Otherwise, this statement will be adopted as comment section by compiler and it will show error.
Son don't code like below:
division = *a /*b; instead of
division = *a / *b; The following segment of code isn't valid.
Floatvar_one, var_two, *a, *b, sum;
Var_one = 10, var_two = 20;
a = &var_one, b = &var_two;
Sum = a + b;
Focus on fourth line. It isn't permitted to operate between two pointer variable. So this statement isn't valid.
But it is permitted to increase or decrease a pointer variable as permitted for pointers. So the following statements are valid for the above code.
Sum = a++;
Sum = sum + *b;
Scale Factor
What will be happened if we increase or decrease or add or subtract with pointer variable? Suppose if we do increment an integer type pointer variable, the value of address of pointer variable will be increased with 4 or 2 (it will depend on system. You can check on your program by sizeof() function.) not 1. And this length of data type is called scale factor. To check this run the following code.
#include <stdio.h>
Int main()
{
Intvar, *ptr;
Ptr = &var;
Printf("Length of integer data type: %d\n",sizeof(int));
Printf("The address of ptr before increment: %u\n",ptr);
++ptr;
Printf("The address of ptr after increment: %u\n",ptr)
}
If the address of pointer variable be 4000 before increment, after increment it will be 4004 or 4002. For constant 1 it will be 4, for constant 2 it will be 3X4 and similarly will go on.
This code for integer data type. You can change this for float, double, char data type.
It is most likely that you would not understand this section until you are through with the chapter 'Pointers'.
Assuming you have some understanding of pointers in C, let us start: An array name is a constant pointer to the first element of the array. Therefore, in the declaration −
Double balance[50];
Balance is a pointer to &balance[0], which is the address of the first element of the array balance. Thus, the following program fragment assigns p as the address of the first element of balance−
Double *p;
Double balance[10];
p = balance;
It is legal to use array names as constant pointers, and vice versa. Therefore, *(balance + 4) is a legitimate way of accessing the data at balance[4].
Once you store the address of the first element in 'p', you can access the array elements using *p, *(p+1), *(p+2) and so on. Given below is the example to show all the concepts discussed above −
#include <stdio.h>
Int main () {
/* an array with 5 elements */
Double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
Double *p;
Inti;
p = balance;
/* output each array element's value */
Printf( "Array values using pointer\n");
For ( i = 0; i< 5; i++ ) {
Printf("*(p + %d) : %f\n", i, *(p + i) );
}
Printf( "Array values using balance as address\n");
For ( i = 0; i< 5; i++ ) {
Printf("*(balance + %d) : %f\n", i, *(balance + i) );
}
Return 0;
}
When the above code is compiled and executed, it produces the following result −
Array values using pointer
*(p + 0) : 1000.000000
*(p + 1) : 2.000000
*(p + 2) : 3.400000
*(p + 3) : 17.000000
*(p + 4) : 50.000000
Array values using balance as address
*(balance + 0) : 1000.000000
*(balance + 1) : 2.000000
*(balance + 2) : 3.400000
*(balance + 3) : 17.000000
*(balance + 4) : 50.000000
In the above example, p is a pointer to double, which means it can store the address of a variable of double type. Once we have the address in p, *p will give us the value available at the address stored in p, as we have shown in the above example.
Let us consider the following example, which uses an array of 3 integers −
#include <stdio.h>
Constint MAX = 3;
Int main () {
Intvar[] = {10, 100, 200};
Inti;
For (i = 0; i< MAX; i++) {
Printf("Value of var[%d] = %d\n", i, var[i] );
}
Return 0;
}
When the above code is compiled and executed, it produces the following result −
Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200
There may be a situation when we want to maintain an array, which can store pointers to an int or char or any other data type available. Following is the declaration of an array of pointers to an integer −
Int *ptr[MAX];
It declares ptr as an array of MAX integer pointers. Thus, each element in ptr, holds a pointer to an int value. The following example uses three integers, which are stored in an array of pointers, as follows −
#include <stdio.h>
Constint MAX = 3;
Int main () {
Intvar[] = {10, 100, 200};
Inti, *ptr[MAX];
For ( i = 0; i< MAX; i++) {
Ptr[i] = &var[i]; /* assign the address of integer. */
}
For ( i = 0; i< MAX; i++) {
Printf("Value of var[%d] = %d\n", i, *ptr[i] );
}
Return 0;
}
When the above code is compiled and executed, it produces the following result −
Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200
You can also use an array of pointers to character to store a list of strings as follows −
#include <stdio.h>
Constint MAX = 4;
Int main () {
Char *names[] = {
"Zara Ali",
"Hina Ali",
"Nuha Ali",
"Sara Ali"
};
Inti = 0;
For ( i = 0; i< MAX; i++) {
Printf("Value of names[%d] = %s\n", i, names[i] );
}
Return 0;
}
When the above code is compiled and executed, it produces the following result −
Value of names[0] = Zara Ali
Value of names[1] = Hina Ali
Value of names[2] = Nuha Ali
Value of names[3] = Sara Ali
A String is a sequence of characters stored in an array. A string always ends with null ('\0') character. Simply a group of characters forms a string and a group of strings form a sentence. A pointer to array of characters or string can be looks like the following:
C Program - Pointers To Strings 1
Pointer-strings-1.c
#include <stdio.h>
Int main()
{
Char *cities[] = {"Iran", "Iraq"};
Inti;
For(i = 0; i< 2; i++)
Printf("%s\n", cities[i]);
Return 0;
}
- Iran
- Iraq
Note:
In the above pointer to string program, we declared a pointer array of character datatypes and then few strings like "Iran", "Iraq" where initialized to the pointer array (*cities[]). Note that we have not declared the size of the array as it is of character pointer type. Coming to the explanation, cities[] is an array which has its own address and it holds the address of first element (I (Iran) ) in it as a value. This address is then executed by the pointer, i.e) pointer start reading the value from the address stored in the array cities[0] and ends with '\0' by default. Next cities[1] holds the address of (I (Iraq).This address is then executed by the pointer, i.e) pointer start reading the value from the address stored in the array cities[1] and ends with '\0' by default. As a result Iran and Iraq is outputted.
C Program - Pointers To Strings 2
Pointer-strings-2.c
#include <stdio.h>
#include <string.h>
Void function(char**);
Int main()
{
Char *str = "Pointer-to-string";
Inti, j = strlen(str);
For(i = 0; i< j; i++)
Printf("%c", *str++);
Return 0;
}
- Pointer-to-string
Note:
*str is a char pointer variable which is initialized by a string "Pointer-to-String". Then strlen() is used to find the length of the string to do iteration using for loop is done to print the complete characters store with the variable name *str.
C programming allows passing a pointer to a function. To do so, simply declare the function parameter as a pointer type.
Following is a simple example where we pass an unsigned long pointer to a function and change the value inside the function which reflects back in the calling function −
#include <stdio.h>
#include <time.h>
VoidgetSeconds(unsigned long *par);
Int main () {
Unsigned long sec;
GetSeconds(&sec );
/* print the actual value */
Printf("Number of seconds: %ld\n", sec );
Return 0;
}
VoidgetSeconds(unsigned long *par) {
/* get the current number of seconds */
*par = time( NULL );
Return;
}
When the above code is compiled and executed, it produces the following result −
Number of seconds :1294450468
The function, which can accept a pointer, can also accept an array as shown in the following example −
#include <stdio.h>
/* function declaration */
DoublegetAverage(int *arr, int size);
Int main () {
/* an int array with 5 elements */
Int balance[5] = {1000, 2, 3, 17, 50};
Doubleavg;
/* pass pointer to the array as an argument */
Avg = getAverage( balance, 5 ) ;
/* output the returned value */
Printf("Average value is: %f\n", avg );
Return 0;
}
DoublegetAverage(int *arr, int size) {
Inti, sum = 0;
Doubleavg;
For (i = 0; i< size; ++i) {
Sum += arr[i];
}
Avg = (double)sum / size;
Returnavg;
}
When the above code is compiled together and executed, it produces the following result −
Average value is: 214.40000
Functions Pointers Example
For example, the next program swaps two values of two:
Void swap (int *a, int *b);
Int main() {
Int m = 25;
Int n = 100;
Printf("m is %d, n is %d\n", m, n);
Swap(&m, &n);
Printf("m is %d, n is %d\n", m, n);
Return 0;}
Void swap (int *a, int *b) {
Int temp;
Temp = *a;
*a = *b;
*b = temp;}
}
Output:
m is 25, n is 100
m is 100, n is 25
The program swaps the actual variables values because the function accesses them by address using pointers. Here we will discuss the program process:
- We declare the function responsible for swapping the two variable values, which takes two integer pointers as parameters and returns any value when it is called.
- In the main function, we declare and initialize two integer variables ('m' and 'n') then we print their values respectively.
- We call the swap() function by passing the address of the two variables as arguments using the ampersand symbol. After that, we print the new swapped values of variables.
- Here we define the swap() function content which takes two integer variable addresses as parameters and declare a temporary integer variable used as a third storage box to save one of the value variables which will be put to the second variable.
- Save the content of the first variable pointed by 'a' in the temporary variable.
- Store the second variable pointed by b in the first variable pointed by a.
- Update the second variable (pointed by b) by the value of the first variable saved in the temporary variable.
Functions with Array Parameters
In C, we cannot pass an array by value to a function. Whereas, an array name is a pointer (address), so we just pass an array name to a function which means to pass a pointer to the array.
For example, we consider the following program:
Intadd_array (int *a, intnum_elements);
Int main() {
Int Tab[5] = {100, 220, 37, 16, 98};
Printf("Total summation is %d\n", add_array(Tab, 5));
Return 0;}
Intadd_array (int *p, int size) {
Int total = 0;
Int k;
For (k = 0; k < size; k++) {
Total += p[k]; /* it is equivalent to total +=*p ;p++; */}
Return (total);}
Output:
Total summation is 471
Here, we will explain the program code with its details
- We declare and define add_array() function which takes an array address( pointer) with its elements number as parameters and returns the total accumulated summation of these elements. The pointer is used to iterate the array elements (using the p[k] notation), and we accumulate the summation in a local variable which will be returned after iterating the entire element array.
- We declare and initialize an integer array with five integer elements. We print the total summation by passing the array name (which acts as address) and array size to the add_array()called function as arguments.
Functions that Return an Array
In C, we can return a pointer to an array, as in the following program:
#include <stdio.h>
Int * build_array();
Int main() {
Int *a;
a = build_array(); /* get first 5 even numbers */
For (k = 0; k < 5; k++)
Printf("%d\n", a[k]);
Return 0;}
Int * build_array() {
Staticint Tab[5]={1,2,3,4,5};
Return (Tab);}
Output:
1
2
3
4
5
And here, we will discuss the program details
- We define and declare a function which returns an array address containing an integer value and didn't take any arguments.
- We declare an integer pointer which receives the complete array built after the function is called and we print its contents by iterating the entire five element array.
Notice that a pointer, not an array, is defined to store the array address returned by the function. Also notice that when a local variable is being returned from a function, we have to declare it as static in the function.
Function Pointers
As we know by definition that pointers point to an address in any memory location, they can also point to at the beginning of executable code as functions in memory.
A pointer to function is declared with the * ,the general statement of its declaration is:
Return_type (*function_name)(arguments)
You have to remember that the parentheses around (*function_name) are important because without them, the compiler will think the function_name is returning a pointer of return_type.
After defining the function pointer, we have to assign it to a function. For example, the next program declares an ordinary function, defines a function pointer, assigns the function pointer to the ordinary function and after that calls the function through the pointer:
#include <stdio.h>
VoidHi_function (int times); /* function */
Int main() {
Void (*function_ptr)(int); /* function pointer Declaration */
Function_ptr = Hi_function; /* pointer assignment */
Function_ptr (3); /* function call */
Return 0;}
VoidHi_function (int times) {
Int k;
For (k = 0; k < times; k++) printf("Hi\n");}
Output:
Hi
Hi
Hi
- We define and declare a standard function which prints a Hi text k times indicated by the parameter times when the function is called
- We define a pointer function (with its special declaration) which takes an integer parameter and doesn't return anything.
- We initialize our pointer function with the Hi_function which means that the pointer points to the Hi_function().
- Rather than the standard function calling by taping the function name with arguments, we call only the pointer function by passing the number 3 as arguments, and that's it!
Keep in mind that the function name points to the beginning address of the executable code like an array name which points to its first element. Therefore, instructions like function_ptr = &Hi_function and (*funptr)(3) are correct.
NOTE: It is not important to insert the address operator & and the indirection operator * during the function assignment and function call.
Array of Function Pointers
An array of function pointers can play a switch or an if statement role for making a decision, as in the next program:
#include <stdio.h>
Int sum(int num1, int num2);
Int sub(int num1, int num2);
Intmult(int num1, int num2);
Int div(int num1, int num2);
Int main()
{ int x, y, choice, result;
Int (*ope[4])(int, int);
Ope[0] = sum;
Ope[1] = sub;
Ope[2] = mult;
Ope[3] = div;
Printf("Enter two integer numbers: ");
Scanf("%d%d", &x, &y);
Printf("Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: ");
Scanf("%d", &choice);
Result = ope[choice](x, y);
Printf("%d", result);
Return 0;}
Int sum(int x, int y) {return(x + y);}
Int sub(int x, int y) {return(x - y);}
Intmult(int x, int y) {return(x * y);}
Int div(int x, int y) {if (y != 0) return (x / y); else return 0;}
Enter two integer numbers: 13 48
Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: 2
624
Here, we discuss the program details:
- We declare and define four functions which take two integer arguments and return an integer value. These functions add, subtract, multiply and divide the two arguments regarding which function is being called by the user.
- We declare 4 integers to handle operands, operation type, and result respectively. Also, we declare an array of four function pointer. Each function pointer of array element takes two integers parameters and returns an integer value.
- We assign and initialize each array element with the function already declared. For example, the third element which is the third function pointer will point to multiplication operation function.
- We seek operands and type of operation from the user typed with the keyboard.
- We called the appropriate array element (Function pointer) with arguments, and we store the result generated by the appropriate function.
The instruction int (*ope[4])(int, int); defines the array of function pointers. Each array element must have the same parameters and return type.
The statement result = ope[choice](x, y); runs the appropriate function according to the choice made by the user The two entered integers are the arguments passed to the function.
Functions Using void Pointers
Void pointers are used during function declarations. We use a void * return type permits to return any type. If we assume that our parameters do not change when passing to a function, we declare it as const.
For example:
Void * cube (const void *);
Consider the following program:
#include <stdio.h>
Void* cube (const void* num);
Int main() {
Int x, cube_int;
x = 4;
Cube_int = cube (&x);
Printf("%d cubed is %d\n", x, cube_int);
Return 0;}
Void* cube (const void *num) {
Int result;
Result = (*(int *)num) * (*(int *)num) * (*(int *)num);
Return result;}
Result:
4 cubed is 64
Here, we will discuss the program details:
- We define and declare a function that returns an integer value and takes an address of unchangeable variable without a specific data type. We calculate the cube value of the content variable (x) pointed by the num pointer, and as it is a void pointer, we have to type cast it to an integer data type using a specific notation (* datatype) pointer, and we return the cube value.
- We declare the operand and the result variable. Also, we initialize our operand with value "4."
- We call the cube function by passing the operand address, and we handle the returning value in the result variable
Function Pointers as Arguments
Another way to exploit a function pointer by passing it as an argument to another function sometimes called "callback function" because the receiving function "calls it back."
In the stdlib.h header file, the Quicksort "qsort()" function uses this technique which is an algorithm dedicated to sort an array.
Voidqsort(void *base, size_tnum, size_t width, int (*compare)(const void *, const void *))
- Void *base : void pointer to the array.
- Size_tnum : The array element number.
- Size_t width The element size.
- Int (*compare (const void *, const void *) : function pointer composed of two arguments and returns 0 when the arguments have the same value, <0 when arg1 comes before arg2, and >0 when arg1 comes after arg2.
The following program sorts an integers array from small to big number using qsort() function:
#include <stdio.h>
#include <stdlib.h>
Int compare (const void *, const void *);
Int main() {
Intarr[5] = {52, 14, 50, 48, 13};
Intnum, width, i;
Num = sizeof(arr)/sizeof(arr[0]);
Width = sizeof(arr[0]);
Qsort((void *)arr, num, width, compare);
For (i = 0; i< 5; i++)
Printf("%d ", arr[ i ]);
Return 0;}
Int compare (const void *elem1, const void *elem2) {
If ((*(int *)elem1) == (*(int *)elem2)) return 0;
Else if ((*(int *)elem1) < (*(int *)elem2)) return -1;
Else return 1;}
Result:
13 14 48 50 52
Here, we will discuss the program details:
- We define compare function composed of two arguments and returns 0 when the arguments have the same value, <0 when arg1 comes before arg2, and >0 when arg1 comes after arg2.The parameters are a void pointers type casted to the appropriate array data type (integer)
- We define and initialize an integer array The array size is stored in the num variable and the size of each array element is stored in width variable using sizeof() predefined C operator.
- We call the qsortfunction and pass the array name, size, width, and comparison function defined previously by the user in order to sort our array in ascending order.The comparison will be performed by taking in each iteration two array elements until the entire array will be sorted.
- We print the array elements to be sure that our array is well sorted by iterating the entire array using for loop.
Text Books:
1. Fundamental of Information Technology by A.Leon&M.Leon.
2. Let Us C by YashwantKanetkar.
3. Computer Fundamentals and Programming in C by A. K. Sharma, Universities Press.
Reference Books:
1. Programming in C by Schaum Series.
2. Computer Networks (4th Edition) by Andrew S. Tanenbaum
3. Digital Principles and Application by Donald Peach, Albert Paul Malvino
4. Operating System Concepts, (6th Edition) by Abraham Silberschatz, Peter Baer Galvin, Greg Gagne