Chapter 7
Chapter 7
Reema Thareja
• Every computer has a primary memory. All our data and programs need to be placed in the primary memory for
execution.
• The primary memory or RAM (Random Access Memory) is a collection of memory locations (often known as
cells) and each location has a specific address. Each memory location is capable of storing 1 byte of data.
• Generally, the computer has three areas of memory each of which is used for a specific task. These areas of
memory are:
Stack: A fixed size of memory is allocated by the system and is filled as needed from bottom to top, one
element at a time. These elements can be removed from the top to the bottom by removing one element at a
time. That is, the last element added to the stack is removed first.
Heap: Heap is a contiguous block of memory locations that is available for use by the program when need
arises. A fixed size heap is allocated by the system and is used by the system in a random fashion.
When the program requests a block of memory, the dynamic allocation technique carves out a block from the
heap and assigns it to the program.
• Global Memory: The block of code that is the main() program (along with other functions in the
program) is stored in the global memory. The memory in the global area is allocated randomly to store
the code of different functions in the program in such a way that one function is not contiguous to
another function. Besides the function code, all global variables declared in the program are stored in
the global memory area.
• Other Memory Layouts: C provides some more memory areas like: text segment, BSS and shared library
segment.
• The text segment is used to store the machine instructions corresponding to the compiled program. This
is generally a read-only memory segment.
• Shared libraries segment contain the executable image of shared libraries that are being used by the
program.
© Oxford University Press 2018. All rights reserved.
Introduction
• Every variable in C has a name and a value associated with it. When a variable is declared, a specific
block of memory within the computer is allocated to hold the value of that variable. The size of the
allocated block depends on the type of the data.
int x = 10;
• When this statement executes, the compiler sets aside 2 bytes of memory to hold the value 10. It also
sets up a symbol table in which it adds the symbol x and the relative address in memory where those 2
bytes were set aside.
• Thus, every variable in C has a value and also a memory location (commonly known as address)
associated with it. Some texts use the term rvalue and lvalue for the value and the address of the
variable respectively.
• The rvalue appears on the right side of the assignment statement and cannot be used on the left side of
the assignment statement. Therefore, writing 10 = k; is illegal.
data_type *ptr_name;
Here, data_type is the data type of the value that the pointer will point to. For example:
int *pnum; char *pch; float *pfnum; int x= 10; int *ptr = &x;
• The '*' informs the compiler that ptr is a pointer variable and the ‘int’ specifies that it will store the
address of an integer variable.
• The & operator retrieves the lvalue (address) of x, and copies that to the contents of the pointer ptr.
• We can "dereference" a pointer, i.e. refer to the value of the variable to which it points by using unary '*'
operator as in *ptr. That is, *ptr = 10, since 10 is value of x.
#include<stdio.h>
int main()
{
int num, *pnum;
pnum = #
printf(“\n Enter the number : ”);
scanf(“%d”, &num);
printf(“\n The number that was entered is : %d”, *pnum);
return 0;
}
Output
Enter the number : 10
The number that was entered is : 10
© Oxford University Press 2018. All rights reserved.
Pointer Expressions and Pointer Arithmetic
• Pointer variables can also be used in expressions. For example
*ptr2 +=1;
• We can add integers to or subtract integers from pointers as well as subtract one pointer from the other.
• We can compare pointers by using relational operators in the expressions. For example p1 > p2 , p1==p2
and p1!=p2 are all valid in C.
• When using pointers, unary increment (++) and decrement (--) operators have greater precedence than
the dereference operator (*). Therefore, the expression *ptr++ is equivalent to *(ptr++).
• In order to increment the value of the variable whose address is stored in ptr, write (*ptr)++.
• A null pointer which is a special pointer value that is known not to point anywhere. This means that a
NULL pointer does not point to any valid memory address.
• To declare a null pointer you may use the predefined constant NULL,
You can always check whether a given pointer variable stores address of some variable or contains a null
by writing,
if ( ptr == NULL)
{ Statement block;
• Null pointers are used in situations if one of the pointers in the program points somewhere some of the
time but not all of the time. In such situations it is always better to set it to a null pointer when it doesn't
point anywhere valid, and to test to see if it's a null pointer before using it.
• A generic pointer is a pointer variable that has void as its data type.
• The generic pointer can be pointed at variables of any data type.
• It is declared by writing void *ptr;
• You need to cast a void pointer to another kind of pointer before using it.
• Generic pointers are used when a pointer has to point to data of different types at different times.
#include<stdio.h>
int main()
{ int x=10;
char ch = ‘A’;
void *gp;
gp = &x; printf("\n Generic pointer points to the integer value = %d", *(int*)gp);
gp = &ch; printf("\n Generic pointer now points to the character %c", *(char*)gp);
return 0;
}
OUTPUT:
Generic pointer points to the integer value = 10
Generic pointer now points to the character = A
© Oxford University Press 2018. All rights reserved.
Passing Arguments to Functions Using Pointers
• The calling function sends the addresses of the variables and the called function must declare those
incoming arguments as pointers.
• In order to modify the variables sent by the caller, the called function must dereference the pointers
that were passed to it. Thus, passing pointers to a function avoids the overhead of copying data from
one function to another.
#include<stdio.h>
void main()
{
int num1, num2, total;
printf(“\n Enter two numbers : “);
scanf(“%d %d”, &num1, &num2);
sum(&num1, &num2, &total);
printf(“\n Total = %d”, total);
}
void sum ( int *a, int *b, int *t)
{
*t = *a + *b;
}
© Oxford University Press 2018. All rights reserved.
Pointers and Arrays
• Array notation is a form of pointer notation.
• The name of the array is the starting address of the array in memory.
• It is also known as the base address. In other words, base address is the address of the first element in
the array or the address of arr[0].
main()
int arr[]={1,2,3,4,5};
• Similarly, writing ptr = &arr[2] makes ptr to point to the third element of the array that has index 2.
• If pointer variable ptr holds the address of the first element in the array, then the address of successive
elements can be calculated by writing ptr++.
#include<stdio.h>
main()
{ int arr[2][2]={{1,2},{3,4}};
int i, (*parr)[2];
parr=arr;
for(i=0;i<2;i++)
{ for(j=0;j<2;j++)
printf(" %d", (*(parr+i))[j]);
}
}
OUTPUT: 1 2 3 4
© Oxford University Press 2018. All rights reserved.
Pointers and Strings
#include<stdio.h>
main()
{ char str[] = “Oxford”; char *pstr = str;
printf(“\n The string is : “);
while( *pstr != ‘\0’)
{ printf(“%c’, *pstr);
pstr++;
}
}
• Here we declare a character pointer *pstr to show the string on the screen. We then "point" the pointer
pstr at str. Then we print each character of the string in the while loop. Instead of using the while loop,
we could have straight away used the function puts(), like
puts(pstr);
• Function prototype for puts() is: int puts(const char *s);
• Here the "const" modifier is used to assure the user that the function will not modify the contents
pointed to by the source pointer.
• If we have declared a pointer to the function, then that pointer can be assigned to the address of the
right sort of function just by using its name.
• When a pointer to a function is declared, it can be called using one of two forms:
(*func)(1,2); OR func(1,2);
#include <stdio.h>
void print(int n);
main()
{
void (*fp)(int); void
print(int value)
{ printf("\n %d", value);
}
include <stdio.h>
int add(int, int);
int subt(int, int);
int operate(int (*operate_fp) (int, int), int, int);
main()
{ int result;
result = operate(add, 9, 7);
printf ("\n Addition Result = %d", result);
result = operate(sub, 9, 7);
printf ("\n Subtraction Result = %d", result);
}
int add (int a, int b)
{ return (a+b);}
nt subtract (int a, int b){ return (a-b);}
int operate(int (*operate_fp) (int, int), int a, int b)
{ int result;
result = (*operate_fp) (a,b);
return result;
} © Oxford University Press 2018. All rights reserved.
Pointers to Pointers
• You can use pointers that point to pointers.
• To declare pointers to pointers just add an asterisk (*) for each level of reference.
int x=10;
px=&x;
x px ppx
ppx=&px;
Now if we write,