Advanced C Programming Techniques
Advanced C Programming Techniques
Winter 2023
Introduction
Pointers
Manipulation of pointers
The special pointer NULL
Pointer arithmetic + and –
Pointers and arrays
The pointer-to void type
Dynamic Memory Allocation
Passing Parameters by value and reference
Functions with a variable number of parameters
Passing Functions as Parameters
Summary and Conclusion
2
Introduction
Pointers are crucial to C, and they are mainly used to:
• Provide the means by which functions can modify their calling arguments.
• Support the dynamic allocation of memory.
• Refer to a large data structure in a simple manner.
• Support data structures such as linked lists.
3
Pointers are Addresses
• A pointer is a variable whose value is a memory addresses.
• A pointer variable is similar to other variables
• It requires memory and stores a value.
• However, the purpose of a pointer is special.
• A data variable stores data (e.g. age ).
• A pointer variable stores memory addresses (of variables)
A pointer contains/stores the
memory address of another
variable (hence it points to
another variable)
4
• Syntax: base type *pointer name;
• where base type defines the type of variable
the pointer can point to.
• Example : int *ptr; float * p1; int *p2;
• ptr is a pointer to an integer variable.
• p1 is a pointer to a float variable
5
Pointers- Simple Example //prelim.c
# include <stdio.h>
int main(void)
{
6
Manipulation of Pointers
Operators:
7
#include <stdio.h>
//ex1.c
int main(void) {
n2 = *ptr; //n2 = value stored at the address pointed by ptr, i.e value of n1
return(0);
}
8
Pointer Declaration and Assignments: Examples:
float z; *ptr2 = 4; // this is equivalent to y=4
x = *ptr2; // this is equivalent to x=y
int x, y;
int *ptr1 = &x // Like any variable, However, the syntax of the following
pointers can be initialized at declaration assignments is not correct:
time with the address of a compatible
ptr1 = x; // type mismatch: assigning
variable, but not with a constant
a data value (integer) to a pointer
int *ptr2 = &y; y = ptr1; // type mismatch: assigning
The syntax of the following assignments an address to an integer variable
is correct: ptr1=&z; // this is wrong because ptr1
ptr2 = ptr1; is supposed to point to an integer variable
/* ptr2 receives the contents of and z is declared as float.
ptr1 which is the address of x in that case
*/
9
*ptr1 = *ptr2; // this is equivalent to x=y
Special Pointer NULL
We need sometimes to indicate that a pointer is not pointing to any valid data. For
that purpose, the constant NULL is defined in stdlib.h and can be used in a C
program.
10
Note:
• Do not deference pointers which are:
• Only declared but not initialized
• Whose value is NULL
11
Pointer Arithmetic
When a pointer is incremented (or decremented), it will point to the memory
location of the next (or previous) element of its base type.
Example :
Assume that ptr, a pointer to int, contains the address 200 and n is an integer.
Also assume that the size of an integer is 4 bytes.
ptr+1 will contain the address 200 + 4=204.
ptr- 1 will contain the address 200 - 4=196.
ptr = ptr + n ptr will contain the address 200 + nx4. //ptr=ptr+2 = ptr+2x4= 208
ptr = ptr - n ptr will contain the addres 200 - nx4. //ptr=ptr-2=ptr-2x4=192
12
//ex3.c
#include <stdio.h>
int main(void)
{
int a=100;
int *p=&a;
printf("\nThe address of p1 %d\n",p);
p=p+1;
printf("\nThe address of p1+1 is %d\n",p);
p=p-1;
printf("\nThe address of p1-1 is %d\n",p);
p=p+2;
printf("\nThe address of p1+2 is %d\n",p);
p=p-2;
printf("\nThe address of p1-2 is %d\n",p);
}
13
Pointers and Arrays
• Pointers and arrays are closely related.
• In particular, the name of an array is the address
of the array’s first element.
• For example, the declaration int ar[3] reserves 3
consecutive units of memory. Each unit has the
same size, size of an integer (e.g., 4 bytes). &ar[0] = 1000, &ar[1] = 1004,
&ar[2] = 1008.
In general, &ar[i] = ar + i 4(size of
integer).
ar corresponds to the address
1000.
ar is a pointer except that it is a
constant.
14
//ex9.c
Pointers and arrays are interchangeable!
Consider the example :
main(){
int ar[4] = {5, 10, 15, 20};
int *ptr;
int i;
for (i=0; i<4; i++)
printf(``%d ``, ar[i]);
ptr=ar; /* Equivalent to ptr=&ar[0] */
for (i=0; i<4; i++)
printf(``%d ``, ptr[i]);
}
Important : Because the name of an array is a constant pointer, it is illegal to make the following assignment
ar =ptr (ptr=ar is fine!)
15
#include <stdio.h> //ex10.c
int main(void){
int ar[4] = {5, 10, 15, 20};
int *ptr; int i;
Valid:
p1=p1-4
p2=p2-3
p3=p1-p2
18
The Pointer to Void Type
• A pointer variable ptr defined as void * ptr is a generic pointer
variable (it can point to any type)
• Advantage : a pointer to void may be converted, without a cast
operation, to a pointer to another data type.
• void *Malloc() //Pointer to Void
19
Important : Pointers to void
void *myfunction(); /* a fn that returns a generic ptr cannot be dereferenced
int n1; Example :
int *ptr1; int n;
float n2; void *ptr=&n;
float *ptr2; *ptr = 25; /* Error */
ptr2 = &n1; /* Error */
ptr1 = &n1; /* OK */
ptr2 = &n2; /* OK */
ptr1 = myfunction(); // OK 'void *' is casted to 'int *' */
ptr2 = myfunction(); // OK, 'void *' is casted to 'float *’
20
# include <stdio.h>
//void.c
main()
{
void * ptr1;
int a=100;
ptr1=&a;
printf("\n The current address of the generic pointer ptr1 is %d\n", ptr1);
float b=20.32;
ptr1= &b;
printf("\n The current address of the generic pointer ptr1 is %d\n", ptr1);
/*
float *temp;
temp =ptr1;
printf("%f",*temp);
*/
}
21
Dynamic Memory Allocation
There are 3 types of memory allocation in C:
Static allocation : a variable's memory is allocated and persists throughout the
entire life of the program. This is the case of global variables.
Automatic allocation : When local variables are declared inside a function, the
space for these variables is allocated when the function is called (starts) and is
freed when the function terminates. This is also the case of parametric
variables.
Dynamic allocation :
Allows a program at the execution time to allocate memory when needed and
to free it when it is no longer needed. Advantage : it is often impossible to
know, prior to the execution time, the size of memory needed in many cases.
For example, the size of an array based on any input size n
22
23
• Through its standard library (include stdlib.h), C provides functions for
allocating new memory from the heap (available unused storage).
• The most commonly used functions for managing dynamic memory are :
• void * malloc(int size) : to allocate a block (number of bytes) of
memory of a given size and returns a pointer to this newly allocated
block.
• void free(void *ptr) : to free a previously allocated block of memory.
• Note: sizeof is an operator often used with malloc. It returns the size in
bytes of its operand(a data type name or a variable name). For instance,
sizeof(char)=1 //so.c
24
Example : ex8.c
main(){
int *ptr1;
float *ptr2;
*ptr1 = 20;
*ptr2 =13.5;
free(ptr1); /* free previously allocated space */
free(ptr2);
} 25
Dynamic Arrays
When the size of an array is not known before the execution time,
allocating arrays dynamically is a good solution.
The steps for creating a dynamic array are :
1. Declare a pointer with an appropriate base type.
2. Call malloc to allocate memory for the elements of the array. The
argument of malloc is equal to the desired size of the array multiplied
by the size in bytes of each element of the array.
3. Assign the result of malloc to the pointer variable.
26
#include <stdio.h>
#include <stdlib.h> //dynarr.c
int main(void) {
int *ar,n;
printf("\nEnter the number of elements in the array\n");
scanf("%d",&n);
ar=malloc(n*sizeof(int));
for(int i=0;i<n;i++)
{
printf("Enter element %d\n", i);
scanf("%d",&ar[i]);
}
printf("\nThe elements of the array are\n");
for(int i=0;i<n;i++)
{
printf("\n%d",ar[i]);
}
free(ar);
//End dynarr.c 27
}
Declared Array vs. Dynamic Array
Declared arrays vs. dynamic arrays
• The memory associated with a declared array is allocated automatically when the function containing the
declaration is called whereas, the memory associated with a dynamic array is not allocated until malloc is
called.
• The size of a declared array is a constant and must be known prior to the execution time whereas, the size
of a dynamic array can be of any size and need not to be known in advance.
IMPORTANT: If the heap runs out of space, malloc will return a NULL instead of a pointer to void
ar = malloc(n * sizeof(float));
if (ar == NULL ) // malloc has failed take-appropriate-action and suitable message has to be displayed
28
Passing Parameters by Address (Reference)
• One of the most common application of pointers in C is their use
as function parameters, making it possible for a function to get
the address of actual parameters.
• When an argument (parameter) is passed by address to a
function, the latter receives the address of the actual argument
which is passed as a pointer from the calling function.
• Passing by values creates copies of the variables and results in
wastage of space and processing power
• Passing by reference is more efficient in terms of memory and
speed.
29
Example: Passing by Reference
#include <stdio.h>
//pbyref.c
int main(void) {
int a = 10;
int b = 20;
swapnum(&a, &b);
printf("\nPassing by reference\n");
printf("After swapping, a is %d and b is %d\n", a, b);
return 0;
}
30
Passing Functions as Pointers
• C allows functions to be passed as arguments.
• How to declare a pointer to functions?
Examples
• Pointer to a function with no parameters and not returning anything.
• void (*ptrFunc)();
• Pointer to a function with one parameter and returning a value double
• double (*ptrFunc)(int)
• ptrFunc=abc;
• Pointer to a function with two parameters and returning a value int
• int (*ptrFunc)(int,int);
31
#include <stdio.h> //ptof.c
int main(void)
{
int (*f1)(int, int);
retvalue=f1(10,20);
printf("\nThe return value is %d\n",retvalue);
}
32
#include <stdio.h>
//fap.c
int print1()
int main(void)
{ {
printf("\nHello World from print1!\n"); helloworld(print1,print2);
return 0; return (0);
}
}
int print2()
{
printf("\nHello World from print2!\n");
return 0;
}
void helloworld(int (*fn)(),int (*fn1)())
{
printf("\n invoking the print function from within helloworld\n");
fn();
fn1();
}
33
#include <stdio.h> //fap9.c
int (*max1)(int,int); int main(void)
int (*max2)(int,int);
{
int ret3=call(maximum,10,6,8,9);
printf("\nThe maximum value is %d\n",ret3);
int maximum(int a,int b)
}
{
if(a>b)
return a;
else
return b;
}
Introduction
Pointers
Manipulation of Pointers
The Special pointer NULL
Pointer arithmetic + and –
Pointers and Arrays
The pointer-to void type
Dynamic Memory Allocation
Passing Parameters by value and Reference
Passing Functions are Parameters
Conclusion
35
THANK YOU
36