1 of 63

1

ICE 1291

Programming with C

Md. Emdadul Haque, PhD.

Professor

Department of ICE, RU

2 of 63

Pointers

Dr. Firoz Ahmed

Professor

Department of ICE, RU

3 of 63

Chapter Outline

  • Introduction
  • Accessing the address of a variable
  • Declaring pointer variable
  • Accessing a variable through its pointer
  • Pointers and arrays
  • Pointers and character string
  • Array of pointers
  • Pointers as function arguments
  • Pointers to function
  • Pointers to structure

3

4 of 63

Introduction

  • A pointer is a derived data types in C
  • It is build from one of the fundamental data types in C
  • Pointers contain memory addresses as their values
  • Since these memory addresses are the locations in the computer memory where instructions and data are stored
    • Pointer can be used to access and manipulate data stored in the memory
  • Pointers are undoubtedly one of the most distinct and exiting features of C language
  • It has added power and flexibility to the language

4

5 of 63

Introduction

  • Pointers offer a number of benefits to the programmers
    • Pointers are more efficient in handling arrays and data tables
    • Pointers can be used to return multiple values from a function via function arguments
    • Pointers permit references to functions and thereby facilitating passing of functions as arguments to other functions
    • The use of pointer arrays to character strings results in saving of data storage space in memory
    • Pointers allow C to support dynamic memory management
    • Pointer provides an efficient tool for manipulating dynamic data structure such as structures, link list, queues, stacks and trees
    • Pointers reduce length and complexity of programs
    • They increase the execution speed and thus reduce the program execution time

5

6 of 63

Introduction

  • Disadvantages of pointers in C
    • Uninitialized pointers might cause segmentation fault
    • Dynamically allocated block needs to be freed explicitly. Otherwise, it would lead to memory leak
    • Pointers are slower than normal variables
    • If pointers are updated with incorrect values, it might lead to memory corruption

6

7 of 63

Introduction

  • pointer is a variable whose value is the address of another variable, i.e., direct address of the memory location

7

8 of 63

Introduction

8

9 of 63

Accessing the address of a variable

  • The actual address of a variable in the memory is system dependent and therefore, the address of a variable is not known to us immediately
  • How can we then determine the address of a variable?
  • This can be done with the help of the operator &
  • We have already seen the use of this address operator in the scanf function
  • The operator & immediately preceding a variable returns the address of the variable associated with it. For example,
    • p = &quantity;
  • It would assign the address 5000 to the variable p
  • The & operator can remembered as ‘address of’

9

10 of 63

Accessing the address of a variable

  • The & operator can be used only with a simple variable or an array element
  • The following are illegal use of address operator
    • &125 (pointing as constant)
    • int s[10]; &x (pointing at array names)
    • &(x+y) (pointing at expression)
  • If x is an array, then expression such as
    • &x[10] and &x[i+3];
  • These are valid and represent the address of 0th and (i+3)th elements of x

10

11 of 63

Declaring pointer variable

  • In C, every variable must be declared for its type
  • Since pointer variables contain addresses that belongs to a separate data type, it must be declared as pointer before it is used
  • The declaration of a pointer variable takes the following form
    • Data_type *pt_name
  • This tells the compiler three things about the variable pt_name
    • The asterisk(*) tells that the variable pt_name is a pointer variable
    • Pt_name needs a memory location
    • Pt_name points to a variable of type data_type

11

12 of 63

Declaring pointer variable

  • For example
    • int *p; /*integer pointer*/
  • It declares the variable p as a pointer variable that points to an integer data type
  • Remember that the type int refers to the data type of the variable being pointed to by p and not the type of the value of the pointer
  • Similarly the statement
    • float *x; /*float pointer*/
  • It declares x as a pointer to a floating point variable

12

13 of 63

Declaring pointer variable

  • Pointer variables are declared similarly as normal variable except for the addition of the unary (*) operator
  • This symbol can be appear anywhere between the type name and the variable name
  • Programmers use the following style
    • int* P;
    • int *p;
    • int * p;
  • However, the second style is becoming increasingly popular due to the following reason
    • It is convenient to have multiple declarations in the same statement. Example: int *p, x, *q;

13

14 of 63

Initialization of pointer variable

  • The process of assigning the address of a variable to a pointer variable is know as initialization

  • All uninitialized pointer will have some unknown values that will be interpreted as memory addresses
  • They may not valid address or they may point to some values that are wrong
  • Since the compiler do not detect these errors, the programmer with uninitialized pointer will produce erroneous result
  • It is therefore important to initialize pointer variables carefully before they are used in the program

14

15 of 63

Initialization of pointer variable

  • Once a pointer variable has been declared we use the assignment operator to initialize the variable
  • Example:

  • We can also combine the initialization with the declaration

  • The only requirement is that the variable quantity must be declare before the initialization take place
  • Remember, this is an initialization of p and not *p

15

16 of 63

Initialization of pointer variable

  • It must be ensured that the pointer variable always point to the corresponding types of data
  • For example

  • The above one will give erroneous output because we are trying to assign the address of float to an integer pointer
  • When we declare a pointer to be of int type, the system assumes that any address that the pointer will hold will point to an integer variable
  • Since the compiler will not detect such errors, care should be taken to avoid wrong pointer arguments

16

17 of 63

Initialization of pointer variable

  • It is possible to combine the declaration of data variable, the declaration pointer variable and the initialization of pointer variable in one step
  • For example int x, *p = &x, is perfectly valid
  • It declares x as an integer variable an p as a pointer variable and then initialize p to the address of x
  • However, int *p = &x, x is not not valid
  • We could also define a pointer variable with an initial value of NULL or 0(zero)

17

18 of 63

Initialization of pointer variable

  • Pointer are flexible, We can make the same pointer to point to different data variable in different statements

  • We can also use different pointers to point to the same data variable

18

19 of 63

Accessing a variable through its pointer

  • Once a pointer has been assigned the address of variable
  • The question is how to access the value of the variable using the pointer?
  • Accessing a variable through its pointer we should follow three steps
    • At first we define a pointer variable
    • Secondly, assign the address of a variable to a pointer
    • Finally, access the value at the address available in the pointer variable
  • This is done by using another unary operator *(asterisk), usually know as indirect operator

19

20 of 63

Accessing a variable through its pointer

  • Consider the following statements:

  • 4th line contains the indirection operator *
  • When the operator * is placed before a pointer variable in an expression, the pointer returns the value of the variable of which the pointer value is the address
  • *p returns the value of the variable quantity, because p is the address of the quantity

20

21 of 63

Accessing a variable through its pointer

21

22 of 63

Accessing a variable through its pointer

22

23 of 63

Pointers and arrays

  • When an array is declared, the compiler allocates a base address and sufficient amount of storage to contain all the elements of the array in contagious memory locations
  • The base address is the location of the first element (index 0) of the array
  • The compiler also defines the array name as a constant pointer to the first element
  • Suppose an array x as follows:
    • Int x[5]={1, 2, 3, 4, 5}

23

24 of 63

Pointers and arrays

  • Suppose the base address of x is 1000 and assuming that each integer requires two bytes
  • The five elements stores as follows:

  • The names x is defined as constant pointer pointing to the first element, x[0]
  • Therefore the value of x is 1000, the location where x[0] is stored. i.e;
    • x = &x[0] = 1000

24

25 of 63

Pointers and arrays

  • If we declare p as an integer pointer, then we can make the pointer p to point to the array x by the following statement
    • p = x; this equivalent to p = &x[0]
  • Now we can access every value of x using p++ to move from one element to another
  • The relationship between x and p is show below:

  • You may noticed that the address of an element is calculated using index and the scale factor of the data type

25

26 of 63

Pointers and arrays

  • For instance,

  • When handling arrays, instead of using array indexing, we can use pointer to access array elements
  • Note that *(p+3) gives the value of x[3]
  • The pointer accessing method is much faster than array indexing

26

27 of 63

Pointers and arrays

27

28 of 63

Pointers and arrays

  • Pointers can be used to manipulate two dimensional arrays as well
  • We know that in a one dimensional array x

  • The above expression represents the element x[i]
  • Similarly an element in a two dimensional array can be represented by the pointer expression

28

29 of 63

Pointers and arrays

29

30 of 63

Pointers and arrays

  • The previous figure illustrates how this expression represents the element a[i][j]
  • The base address of the array a is &a[0][0] and starting at this address
  • The compiler allocates contiguous space for all the element row-wise
  • That is, the first element of the second row is placed immediately after the last element of the first row and so on

30

31 of 63

Pointers and arrays

  • Suppose we declare an array as follows

  • The element of a will be stored as:

  • If we declare p as an int pointer with the initial address of a[0][0]
  • Then a[i][j] is equivalent to *(p+4 x i + j)
  • The element a[2][3] is given by *(p + 2 x 4 + 3)

31

32 of 63

Pointers and character string

  • Strings are treated like character arrays and therefore they are declared and initialized as follows
    • Char str [6] = “Hello”
  • The compiler automatically insert the null character “\0” at the end of the string
  • The above string can be represented as follows

  • Each character in the string str takes 1 byte of memory space

32

33 of 63

Pointers and character string

  • C support an alternative method to create strings using pointer variable of type char
    • Example: Char *ptr = str
  • We can represent the character pointer variable ptr as follows:

33

34 of 63

Pointers and character string

34

35 of 63

Array of pointers

  • One important use of pointer is in handling of table of strings
  • Consider the following array of strings
    • Char name [3][25]
  • This says that the name is a table containing three names
  • Each with a maximum length of 25 character
  • The total storage requirement for the name table are 75 bytes

35

36 of 63

Array of pointers

  • We know that rarely the individual strings will be of equal lengths
  • Therefore instead of making each row a fixed number of characters
  • We can make it a pointer to a string of varying length
  • Like an array of variables, we also use array of pointers in C
  • An array of pointers is an indexed set of variables, where the variables are pointers
  • An array of pointers is useful for the same reason that all arrays are useful
  • It allows to numerically index a large set of variables

36

37 of 63

Array of pointers

  • For example

  • Declares name to be an array of three pointers to characters
  • Each pointer pointing to a particular name as:

37

38 of 63

Array of pointers

  • This declaration allocates only 28 bytes, sufficient to hold all the character as shown

  • The following statement would print out all the three names

  • To access the jth character in the ith name, we may write as

38

39 of 63

Array of pointers

39

40 of 63

Array of pointers

  • Difference between pointer to an array and array of pointers
    • int *a[10];
      • Declares and allocates an array of pointers to int
      • Each element must be dereferenced individually.
    • int (*a)[10];
      • Declares (without allocating) a pointer to an array of int(s)
      • The pointer to the array must be dereferenced to access the value of each element.
    • int a[10];
      • Declares and allocates an array of int(s).

40

41 of 63

Array of pointers

    • Pointer to an array:
      • Pointer to an array is also known as array pointer
      • We are using the pointer to access the components of the array
        • int a[3] = {3, 4, 5 };
        • int *ptr = a;
      • We have a pointer ptr that focuses to the 0th component of the array
      • We can likewise declare a pointer that can point to whole array rather than just a single component of the array

41

42 of 63

Array of pointers

      • Syntax:
        • data type (*var name)[size of array];
      • Declaration of the pointer to an array:
        • // pointer to an array of five numbers
        • int (* ptr)[5] = NULL;
      • The above declaration is the pointer to an array of five integers
      • We use parenthesis to pronounce pointer to an array
      • Since subscript has higher priority than indirection, it is crucial to encase the indirection operator and pointer name inside brackets

42

43 of 63

Array of pointers

43

44 of 63

Array of pointers

    • Array of pointers
      • It is an array of the pointer variables
      • It is also known as pointer arrays
      • Syntax:
        • int *var_name[array_size];
      • Declaration of an array of pointers:
        • int *ptr[3];
      • We can make separate pointer variables which can point to the different values or we can make one integer array of pointers that can point to all the values

44

45 of 63

Array of pointers

45

46 of 63

Array of pointers

  • Remember the difference between the notations *p[3] and (*p)[3]
  • Since * has a lower precedence than [], *p[3] declares p as an array of 3 pointers while (*p)[3] declares p as a pointer to an array of three elements

46

47 of 63

Pointers as function arguments

  • When an array is passed to a function as an argument, the actual values of the array elements is not passed
    • Only the address of the first element of the array is passed
  • If x is an array, when we call sort(x), the address of x[0] is passed to the function sort
  • The function uses this address for manipulating the array element
  • Similarly, we can pass the address of a variable as an argument to a function in the normal fashion
  • When we pass address to a function, the parameters receiving the addresses should be pointers

47

48 of 63

Pointers as function arguments

  • How to declare a function which accepts a pointer as an argument?
    • If a function wants to accept an address of an integer variable then the function declaration will be
      • return_type function_name(int*);
        • ‘*’ indicates that the argument is an address of a variable not the value of a variable
    • Similarly, If a function wants to accept an address of two integer variable then the function declaration will be,
      • return_type function_name(int*,int*);
  • The process of calling a function using pointer to pass the addresses of variable is known as “call by reference
  • The function which is called by “reference” can changed the value of the variable used in the call

48

49 of 63

Pointers as function arguments

  • What will happen to the argument?
    • Here, we are passing the address of a variable
    • So, if we change the argument value in the function, it will modify the actual value of a variable

49

50 of 63

Pointers as function arguments

  • Step 1. Address of a variable a 1024 is passed to function setToZero()
  • Step 2. *a = 0 will modify the original value of a. So, a value in main function will be 0 after the function execution

50

51 of 63

Pointers as function arguments

  • To pass a pointer as function argument, the following points may be noted
    • The function parameters are declared as pointer
    • The dereferenced pointers are used in the function body
    • When the function is called, the address are passed as actual arguments

51

52 of 63

Pointers to function

  • A function, like a variable, has a type and an address location in the memory

52

53 of 63

Pointers to function

  • It is therefore, possible to declare a pointer to a function, which can then be used as an argument in another function
  • A pointer to function or function pointer stores the address of the function
  • Though it doesn't point to any data. It points to the first instruction in the function
  • A pointer to a function is declared as follows

  • This tells the compiler that fptr is a pointer to a function, which returns type value

53

54 of 63

Pointers to function

  • Example
    • void (*fptr)();
      • We must enclose the function pointer variable with (). like (*fptr)
      • Where *fptr is a function pointer, capable of referring a function whose return type is void and also it will not take any argument ()
    • Similarly, if we want to point a function whose return type is int and it takes one integer argument i.e. int fun(int); then the declaration will be
      • int (*fptr)(int);
  • Remember, the statement like int *fptr(int); would declare fptr as a function returning a pointer to type

54

55 of 63

Pointers to function

  • We can make a function pointer to point to a specific function by simple assigning the name of the function to the pointer
  • For example

  • The above statements declare p1 as pointer to a function and mul as a function then make p1 to point to the function mul
  • To call the function mul, we may now use the pointer p1 with the list of parameters. That is,

  • It is equivalent to mul(x,y)

55

56 of 63

Pointers to function

56

57 of 63

Pointers to structure

  • We know that the name of an array stands for the address of its zeroth element
  • The same things is true of the names of arrays of structure variable
  • Consider the following declaration

  • Suppose product is an array variable of struct type
  • The name product represents the address of its zeroth element

57

58 of 63

Pointers to structure

  • This statement declares product as an array of two elements, each of the type struct inventory
  • ptr as a pointer of data object of the type struct inventory
  • The assignment ptr = product; would assign the address of the zeroth element of product to ptr
  • That is, the pointer ptr will now point to product[0]
  • Its members can be accessed using the following notation

  • The symbol 🡪 is called the arrow operator (also know as member selection operator)
  • Note that ptr🡪 is simple another way of writing product[0]

58

59 of 63

Pointers to structure

  • When the pointer ptr incremented by one, it is made to point to the next record, i.e., product[1]
  • The following for statement will print the values of members of all the elements of product array

  • We could also use the notation (*ptr).number to access the member number
  • The parenthesis around *ptr are necessary because the member operator ‘.’ has a higher precedence than the operator ‘*’

59

60 of 63

Pointers to structure

60

61 of 63

Pointers to structure

  • While using structure pointers, we should take care of the precedence of operators
  • The operator ‘🡪’ and ‘.’, and () and [] enjoy the highest priority among the operators
  • For example

  • ++ptr🡪count; increments count, not ptr
  • (++ptr)🡪count; increments ptr first and then link count
  • Ptr++🡪count; is legal and increments ptr after accessing count

61

62 of 63

Pointers to structure

  • The following statement also behave in the similar fashion

  • If a function receives a copy of an entire structure and returns it after working on it
  • This method is insufficient in terms of both, the execution speed and memory
  • It can be overcome by passing a pointer to the structure and then using this pointer to work on the structure member

62

63 of 63

Pointers to structure

  • Consider the following function:

  • The function can be called by

  • The formal argument item receives the address of the structure product
  • Therefore it must be declared as a pointer of type struct invent, which represents the structure of product

63